]> git.ipfire.org Git - thirdparty/glibc.git/blame - sysdeps/unix/sysv/linux/tst-setgetname.c
Update copyright dates with scripts/update-copyrights.
[thirdparty/glibc.git] / sysdeps / unix / sysv / linux / tst-setgetname.c
CommitLineData
1db94db1 1/* Test pthread_setname_np and pthread_getname_np.
04277e02 2 Copyright (C) 2013-2019 Free Software Foundation, Inc.
1db94db1
CD
3 This file is part of the GNU C Library.
4
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public License as
7 published by the Free Software Foundation; either version 2.1 of the
8 License, or (at your option) any later version.
9
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; see the file COPYING.LIB. If
17 not, see <http://www.gnu.org/licenses/>. */
18#include <stdio.h>
19#include <stdlib.h>
20#include <pthread.h>
21#include <string.h>
22#include <sys/syscall.h>
23#include <unistd.h>
24#include <fcntl.h>
25#include <errno.h>
26
27/* New name of process. */
28#define NEW_NAME "setname"
29
30/* Name of process which is one byte too big
31 e.g. 17 bytes including null-terminator */
32#define BIG_NAME "....V....X....XV"
33
34/* Longest name of a process
35 e.g. 16 bytes including null-terminator. */
36#define LONGEST_NAME "....V....X....X"
37
38/* One less than longest name with unique
39 characters to detect modification. */
40#define CANARY_NAME "abcdefghijklmn"
41
42/* On Linux the maximum length of the name of a task *including* the null
43 terminator. */
44#define TASK_COMM_LEN 16
45
46long
47gettid (void)
48{
49 return syscall(__NR_gettid);
50}
51
52/* On Linux we can read this task's name from /proc. */
53int
54get_self_comm (long tid, char *buf, size_t len)
55{
56 int res = 0;
57#define FMT "/proc/self/task/%lu/comm"
93f94163 58 char fname[sizeof (FMT) + 32];
1db94db1
CD
59 sprintf (fname, FMT, (unsigned long) tid);
60
61 int fd = open (fname, O_RDONLY);
62 if (fd == -1)
63 return errno;
64
65 ssize_t n = read (fd, (void *) buf, len);
66 if (n < 0)
67 res = errno;
68 else
69 {
70 if (buf[n - 1] == '\n')
71 buf[n - 1] = '\0';
72 else if (n == len)
73 res = ERANGE;
74 else
75 buf[n] = '\0';
76 }
77
78 close (fd);
79 return res;
80}
81
82int
83do_test (int argc, char **argv)
84{
85 pthread_t self;
86 int res;
87 int ret = 0;
88 char name[TASK_COMM_LEN];
89 char name_check[TASK_COMM_LEN];
90
91 memset (name, '\0', TASK_COMM_LEN);
92 memset (name_check, '\0', TASK_COMM_LEN);
93
94 /* Test 1: Get the name of the task via pthread_getname_np and /proc
95 and verify that they both match. */
96 self = pthread_self ();
97 res = pthread_getname_np (self, name, TASK_COMM_LEN);
98
99 if (res == 0)
100 {
101 res = get_self_comm (gettid (), name_check, TASK_COMM_LEN);
f877c4f2 102
1db94db1
CD
103 if (res == 0)
104 {
105 if (strncmp (name, name_check, strlen (BIG_NAME)) == 0)
106 printf ("PASS: Test 1 - pthread_getname_np and /proc agree.\n");
107 else
108 {
109 printf ("FAIL: Test 1 - pthread_getname_np and /proc differ"
110 " i.e. %s != %s\n", name, name_check);
111 ret++;
112 }
113 }
114 else
115 {
116 printf ("FAIL: Test 1 - unable read task name via proc.\n");
117 ret++;
118 }
119 }
120 else
121 {
122 printf ("FAIL: Test 1 - pthread_getname_np failed with error %d\n", res);
123 ret++;
124 }
125
126 /* Test 2: Test setting the name and then independently verify it
127 was set. */
128 res = pthread_setname_np (self, NEW_NAME);
129
130 if (res == 0)
131 {
132 res = get_self_comm (gettid (), name_check, TASK_COMM_LEN);
133 if (res == 0)
134 {
135 if (strncmp (NEW_NAME, name_check, strlen (BIG_NAME)) == 0)
136 printf ("PASS: Test 2 - Value used in pthread_setname_np and"
137 " /proc agree.\n");
138 else
139 {
140 printf ("FAIL: Test 2 - Value used in pthread_setname_np"
141 " and /proc differ i.e. %s != %s\n",
142 NEW_NAME, name_check);
143 ret++;
144 }
145 }
146 else
147 {
148 printf ("FAIL: Test 2 - unable to read task name via proc.\n");
149 ret++;
150 }
151 }
152 else
153 {
154 printf ("FAIL: Test 2 - pthread_setname_np failed with error %d\n", res);
155 ret++;
156 }
157
158 /* Test 3: Test setting a name that is one-byte too big. */
159 res = pthread_getname_np (self, name, TASK_COMM_LEN);
160
161 if (res == 0)
162 {
163 res = pthread_setname_np (self, BIG_NAME);
164 if (res != 0)
165 {
166 if (res == ERANGE)
167 {
168 printf ("PASS: Test 3 - pthread_setname_np returned ERANGE"
169 " for a process name that was too long.\n");
170
171 /* Verify the old name didn't change. */
172 res = get_self_comm (gettid (), name_check, TASK_COMM_LEN);
173 if (res == 0)
174 {
175 if (strncmp (name, name_check, strlen (BIG_NAME)) == 0)
176 printf ("PASS: Test 3 - Original name unchanged after"
177 " pthread_setname_np returned ERANGE.\n");
178 else
179 {
180 printf ("FAIL: Test 3 - Original name changed after"
181 " pthread_setname_np returned ERANGE"
182 " i.e. %s != %s\n",
183 name, name_check);
184 ret++;
185 }
186 }
187 else
188 {
189 printf ("FAIL: Test 3 - unable to read task name.\n");
190 ret++;
191 }
192 }
193 else
194 {
195 printf ("FAIL: Test 3 - Wrong error returned"
196 " i.e. ERANGE != %d\n", res);
197 ret++;
198 }
199 }
200 else
201 {
202 printf ("FAIL: Test 3 - Too-long name accepted by"
203 " pthread_setname_np.\n");
204 ret++;
205 }
206 }
207 else
208 {
209 printf ("FAIL: Test 3 - Unable to get original name.\n");
210 ret++;
211 }
212
213 /* Test 4: Verify that setting the longest name works. */
214 res = pthread_setname_np (self, LONGEST_NAME);
215
216 if (res == 0)
217 {
218 res = get_self_comm (gettid (), name_check, TASK_COMM_LEN);
219 if (res == 0)
220 {
221 if (strncmp (LONGEST_NAME, name_check, strlen (BIG_NAME)) == 0)
222 printf ("PASS: Test 4 - Longest name set via pthread_setname_np"
223 " agrees with /proc.\n");
224 else
225 {
226 printf ("FAIL: Test 4 - Value used in pthread_setname_np and /proc"
227 " differ i.e. %s != %s\n", LONGEST_NAME, name_check);
228 ret++;
229 }
230 }
231 else
232 {
233 printf ("FAIL: Test 4 - unable to read task name via proc.\n");
234 ret++;
235 }
236 }
237 else
238 {
239 printf ("FAIL: Test 4 - pthread_setname_np failed with error %d\n", res);
240 ret++;
241 }
242
243 /* Test 5: Verify that getting a long name into a small buffer fails. */
244 strncpy (name, CANARY_NAME, strlen (CANARY_NAME) + 1);
245
246 /* Claim the buffer length is strlen (LONGEST_NAME). This is one character
247 too small to hold LONGEST_NAME *and* the null terminator. We should get
248 back ERANGE and name should be unmodified. */
249 res = pthread_getname_np (self, name, strlen (LONGEST_NAME));
250
251 if (res != 0)
252 {
253 if (res == ERANGE)
254 {
255 if (strncmp (CANARY_NAME, name, strlen (BIG_NAME)) == 0)
256 {
257 printf ("PASS: Test 5 - ERANGE and buffer unmodified.\n");
258 }
259 else
260 {
261 printf ("FAIL: Test 5 - Original buffer modified.\n");
262 ret++;
263 }
264 }
265 else
266 {
267 printf ("FAIL: Test 5 - Did not return ERANGE for small buffer.\n");
268 ret++;
269 }
270 }
271 else
272 {
273 printf ("FAIL: Test 5 - Returned name longer than buffer.\n");
274 ret++;
275 }
276
277 /* Test 6: Lastly make sure we can read back the longest name. */
278 res = pthread_getname_np (self, name, strlen (LONGEST_NAME) + 1);
279
280 if (res == 0)
281 {
282 if (strncmp (LONGEST_NAME, name, strlen (BIG_NAME)) == 0)
283 {
284 printf ("PASS: Test 6 - Read back longest name correctly.\n");
285 }
286 else
287 {
288 printf ("FAIL: Test 6 - Read \"%s\" instead of longest name.\n",
289 name);
290 ret++;
291 }
292 }
293 else
294 {
295 printf ("FAIL: Test 6 - pthread_getname_np failed with error %d\n", res);
296 ret++;
297 }
298
299 return ret;
300}
301
302#include <test-skeleton.c>