1 /* 2 * This file and its contents are supplied under the terms of the 3 * Common Development and Distribution License ("CDDL"), version 1.0. 4 * You may only use this file in accordance with the terms of version 5 * 1.0 of the CDDL. 6 * 7 * A full copy of the text of the CDDL should have accompanied this 8 * source. A copy of the CDDL is also available via the Internet at 9 * http://www.illumos.org/license/CDDL. 10 */ 11 12 /* 13 * Copyright 2018 Joyent, Inc. 14 */ 15 16 /* 17 * Some basic pthread name API tests. 18 */ 19 20 #include <sys/stat.h> 21 #include <pthread.h> 22 #include <limits.h> 23 #include <stdlib.h> 24 #include <string.h> 25 #include <unistd.h> 26 #include <thread.h> 27 #include <fcntl.h> 28 #include <stdio.h> 29 #include <errno.h> 30 #include <err.h> 31 32 33 /*ARGSUSED*/ 34 static void * 35 thr(void *unused) 36 { 37 (void) sleep(100); 38 return (NULL); 39 } 40 41 /*ARGSUSED*/ 42 int 43 main(int argc, char *argv[]) 44 { 45 char name[PTHREAD_MAX_NAMELEN_NP]; 46 pthread_attr_t attr; 47 char path[PATH_MAX]; 48 pthread_t tid; 49 ssize_t n; 50 int test; 51 int rc; 52 int fd; 53 54 /* Default thread name is empty string. */ 55 test = 1; 56 57 rc = pthread_getname_np(pthread_self(), name, sizeof (name)); 58 59 if (rc != 0 || strcmp(name, "") != 0) 60 errx(EXIT_FAILURE, "test %d failed with %d", test, rc); 61 62 /* Can set name. */ 63 test = 2; 64 65 (void) strlcpy(name, "main", sizeof (name)); 66 rc = pthread_setname_np(pthread_self(), name); 67 68 if (rc != 0) 69 errx(EXIT_FAILURE, "test %d failed with %d", test, rc); 70 71 rc = pthread_getname_np(pthread_self(), name, sizeof (name)); 72 73 if (rc != 0 || strcmp(name, "main") != 0) 74 errx(EXIT_FAILURE, "test %d failed with %d", test, rc); 75 76 /* ERANGE check. */ 77 test = 3; 78 79 rc = pthread_getname_np(pthread_self(), name, 2); 80 81 if (rc != ERANGE) 82 errx(EXIT_FAILURE, "test %d failed with %d", test, rc); 83 84 /* EINVAL check. */ 85 test = 4; 86 87 rc = pthread_getname_np(pthread_self(), NULL, sizeof (name)); 88 89 if (rc != EINVAL) 90 errx(EXIT_FAILURE, "test %d failed with %d", test, rc); 91 92 /* can clear thread name. */ 93 test = 5; 94 95 rc = pthread_setname_np(pthread_self(), NULL); 96 97 if (rc != 0) 98 errx(EXIT_FAILURE, "test %d failed with %d", test, rc); 99 100 rc = pthread_getname_np(pthread_self(), name, sizeof (name)); 101 102 if (rc != 0 || strcmp(name, "") != 0) 103 errx(EXIT_FAILURE, "test %d failed with %d", test, rc); 104 105 /* non-existent thread check. */ 106 test = 6; 107 108 rc = pthread_getname_np(808, name, sizeof (name)); 109 110 if (rc != ESRCH) 111 errx(EXIT_FAILURE, "test %d failed with %d", test, rc); 112 113 rc = pthread_setname_np(808, "state"); 114 115 if (rc != ESRCH) 116 errx(EXIT_FAILURE, "test %d failed with %d", test, rc); 117 118 /* too long a name. */ 119 test = 7; 120 121 rc = pthread_setname_np(pthread_self(), 122 "12345678901234567890123456789012"); 123 124 if (rc != ERANGE) 125 errx(EXIT_FAILURE, "test %d failed with %d", test, rc); 126 127 /* can name another thread. */ 128 test = 8; 129 130 rc = pthread_create(&tid, NULL, thr, NULL); 131 132 if (rc != 0) 133 errx(EXIT_FAILURE, "test %d failed with %d", test, rc); 134 135 rc = pthread_setname_np(tid, "otherthread"); 136 137 if (rc != 0) 138 errx(EXIT_FAILURE, "test %d failed with %d", test, rc); 139 140 /* attr tests. */ 141 test = 9; 142 143 (void) pthread_attr_init(&attr); 144 145 rc = pthread_attr_setname_np(&attr, 146 "12345678901234567890123456789012"); 147 148 if (rc != ERANGE) 149 errx(EXIT_FAILURE, "test %d failed with %d", test, rc); 150 151 rc = pthread_attr_setname_np(&attr, "thread2"); 152 153 if (rc != 0) 154 errx(EXIT_FAILURE, "test %d failed with %d", test, rc); 155 156 rc = pthread_attr_getname_np(&attr, NULL, sizeof (name)); 157 158 if (rc != EINVAL) 159 errx(EXIT_FAILURE, "test %d failed with %d", test, rc); 160 161 rc = pthread_attr_getname_np(&attr, name, 2); 162 163 if (rc != ERANGE) 164 errx(EXIT_FAILURE, "test %d failed with %d", test, rc); 165 166 /* does the attr actually apply? */ 167 test = 10; 168 169 rc = pthread_create(&tid, &attr, thr, NULL); 170 171 if (rc != 0) 172 errx(EXIT_FAILURE, "test %d failed with %d", test, rc); 173 174 rc = pthread_getname_np(tid, name, sizeof (name)); 175 176 if (rc != 0 || strcmp(name, "thread2") != 0) 177 errx(EXIT_FAILURE, "test %d failed with %d", test, rc); 178 179 /* proc read tests */ 180 test = 11; 181 182 (void) snprintf(path, sizeof (path), 183 "/proc/self/lwp/%d/lwpname", (int)tid); 184 185 fd = open(path, O_RDWR); 186 187 if (fd == -1) 188 errx(EXIT_FAILURE, "test %d failed with %d", test, errno); 189 190 n = read(fd, name, sizeof (name)); 191 192 if (n != sizeof (name) || strcmp(name, "thread2") != 0) 193 errx(EXIT_FAILURE, "test %d failed with %d", test, rc); 194 195 if (lseek(fd, 0, SEEK_SET) != 0) 196 errx(EXIT_FAILURE, "test %d failed with %d", test, errno); 197 198 n = read(fd, name, PTHREAD_MAX_NAMELEN_NP * 2); 199 200 if (n != sizeof (name) || strcmp(name, "thread2") != 0) 201 errx(EXIT_FAILURE, "test %d failed with %d", test, rc); 202 203 if (lseek(fd, 0, SEEK_SET) != 0) 204 errx(EXIT_FAILURE, "test %d failed with %d", test, errno); 205 206 n = read(fd, name, 4); 207 208 if (n != 4 || strncmp(name, "thre", 4) != 0) 209 errx(EXIT_FAILURE, "test %d failed with %d", test, rc); 210 211 /* proc write tests */ 212 test = 12; 213 214 if (lseek(fd, 0, SEEK_SET) != 0) 215 errx(EXIT_FAILURE, "test %d failed with %d", test, errno); 216 217 n = write(fd, "1234567890123456789012345678901", 218 PTHREAD_MAX_NAMELEN_NP); 219 220 if (n != PTHREAD_MAX_NAMELEN_NP) 221 errx(EXIT_FAILURE, "test %d failed with %d", test, errno); 222 223 if (lseek(fd, 0, SEEK_SET) != 0) 224 errx(EXIT_FAILURE, "test %d failed with %d", test, errno); 225 226 n = write(fd, "foo", sizeof ("foo")); 227 228 if (n != sizeof ("foo")) 229 errx(EXIT_FAILURE, "test %d failed with %d", test, errno); 230 231 if (lseek(fd, 0, SEEK_SET) != 0) 232 errx(EXIT_FAILURE, "test %d failed with %d", test, errno); 233 234 n = read(fd, name, sizeof (name)); 235 236 if (n != sizeof (name) || strcmp(name, "foo") != 0) 237 errx(EXIT_FAILURE, "test %d failed with %d", test, rc); 238 239 (void) close(fd); 240 241 /* thr_* API. */ 242 test = 13; 243 244 rc = thr_setname(thr_self(), "main"); 245 246 if (rc != 0) 247 errx(EXIT_FAILURE, "test %d failed with %d", test, rc); 248 249 rc = thr_getname(thr_self(), name, sizeof (name)); 250 251 if (rc != 0 || strcmp(name, "main") != 0) 252 errx(EXIT_FAILURE, "test %d failed with %d", test, rc); 253 254 /* badness */ 255 test = 14; 256 257 rc = thr_setname(thr_self(), "\033]0;messeduptitle\a"); 258 259 if (rc != EINVAL) 260 errx(EXIT_FAILURE, "test %d failed with %d", test, rc); 261 262 rc = thr_setname(thr_self(), "ab\177\177\n"); 263 264 if (rc != EINVAL) 265 errx(EXIT_FAILURE, "test %d failed with %d", test, rc); 266 267 rc = pthread_attr_setname_np(&attr, "\033]0;messeduptitle\a"); 268 269 if (rc != EINVAL) 270 errx(EXIT_FAILURE, "test %d failed with %d", test, rc); 271 272 rc = pthread_attr_setname_np(&attr, "ab\177\177\n"); 273 274 if (rc != EINVAL) 275 errx(EXIT_FAILURE, "test %d failed with %d", test, rc); 276 277 return (EXIT_SUCCESS); 278 }