tst-setgetname.c 8.1 KB

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