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