diff --git a/libc-test/src/functional/pthread_getname_np.c b/libc-test/src/functional/pthread_getname_np.c new file mode 100644 index 0000000000000000000000000000000000000000..19a46c61a70d64ea9bfbaa6ef426ca33a8d65fbc --- /dev/null +++ b/libc-test/src/functional/pthread_getname_np.c @@ -0,0 +1,49 @@ +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include + +#define NAMELEN 16 + +#define errExitEN(en, msg) \ + do { errno = en; perror(msg); exit(EXIT_FAILURE); \ + } while (0) + +static void *threadfunc(void *parm) +{ + sleep(5); // allow main program to set the thread name + return NULL; +} + +int main(int argc, char **argv) +{ + pthread_t thread; + int rc; + char thread_name[NAMELEN]; + char set_thread_name[] = "THREADFOO"; + char default_name[] = "pthread_getname_np"; + + rc = pthread_getname_np(pthread_self(), thread_name, NAMELEN); + if (rc != 0) errExitEN(rc, "pthread_getname_np failed"); + if(strcmp(thread_name, default_name) != 0) perror("pthread name comparison failed"); + + rc = pthread_create(&thread, NULL, threadfunc, NULL); + if (rc != 0) errExitEN(rc, "pthread_create failed"); + + rc = pthread_setname_np(thread, (argc > 1) ? argv[1] : set_thread_name); + if (rc != 0) errExitEN(rc, "pthread_setname_np failed"); + + sleep(2); + + rc = pthread_getname_np(thread, thread_name, (argc > 2) ? atoi(argv[1]) : NAMELEN); + if (rc != 0) errExitEN(rc, "pthread_getname_np failed"); + if(strcmp(thread_name, set_thread_name) != 0) perror("pthread name comparison failed"); + + rc = pthread_join(thread, NULL); + if (rc != 0) errExitEN(rc, "pthread_join failed"); + + exit(EXIT_SUCCESS); +} \ No newline at end of file diff --git a/libc-test/src/functional/test_src_functional.gni b/libc-test/src/functional/test_src_functional.gni index a6173354043cd267f53e4296e4f6c75be6e0c1ca..85d0754386a4ce1b7586812b73fead5168254be1 100644 --- a/libc-test/src/functional/test_src_functional.gni +++ b/libc-test/src/functional/test_src_functional.gni @@ -29,6 +29,7 @@ functional_list = [ "pthread_mutex_pi", "pthread_robust", "pthread_tsd", + "pthread_getname_np", "qsort", "random", "search_hsearch", diff --git a/musl_src.gni b/musl_src.gni index 7f1b005a851400d7254a62f58d8d7e92eaaf21fa..958bb000ec78e73d8673d61662af0d93635f07e5 100644 --- a/musl_src.gni +++ b/musl_src.gni @@ -1293,6 +1293,7 @@ musl_src_file = [ "src/thread/pthread_getattr_np.c", "src/thread/pthread_getconcurrency.c", "src/thread/pthread_getcpuclockid.c", + "src/thread/pthread_getname_np.c", "src/thread/pthread_getschedparam.c", "src/thread/pthread_getspecific.c", "src/thread/pthread_join.c", @@ -1939,6 +1940,7 @@ musl_src_porting_file = [ "src/time/strftime.c", "src/time/strptime.c", "src/time/time_impl.h", + "src/thread/pthread_getname_np.c", ] musl_inc_hook_files = [ diff --git a/porting/linux/user/include/pthread.h b/porting/linux/user/include/pthread.h index ea9833282a89b885d6961fbb6d5d13095b12c0d6..45184fced76adaf4b83f071e7a2a2211ca4d94d7 100644 --- a/porting/linux/user/include/pthread.h +++ b/porting/linux/user/include/pthread.h @@ -395,6 +395,7 @@ int pthread_getaffinity_np(pthread_t, size_t, struct cpu_set_t *); int pthread_setaffinity_np(pthread_t, size_t, const struct cpu_set_t *); int pthread_getattr_np(pthread_t, pthread_attr_t *); int pthread_setname_np(pthread_t, const char *); +int pthread_getname_np(pthread_t, char *, size_t); int pthread_getattr_default_np(pthread_attr_t *); int pthread_setattr_default_np(const pthread_attr_t *); int pthread_tryjoin_np(pthread_t, void **); diff --git a/porting/linux/user/src/thread/pthread_getname_np.c b/porting/linux/user/src/thread/pthread_getname_np.c new file mode 100644 index 0000000000000000000000000000000000000000..5d99673a80bf6c601fc84d144201ab97218e5c8e --- /dev/null +++ b/porting/linux/user/src/thread/pthread_getname_np.c @@ -0,0 +1,29 @@ +#define _GNU_SOURCE +#include +#include +#include + +#include "pthread_impl.h" + +int pthread_getname_np(pthread_t thread, char *name, size_t len) +{ + int fd, cs, status = 0; + char f[sizeof "/proc/self/task//comm" + 3*sizeof(int)]; + + if (len < 16) return ERANGE; + + if (thread == pthread_self()) + return prctl(PR_GET_NAME, (unsigned long)name, 0UL, 0UL, 0UL) ? errno : 0; + + snprintf(f, sizeof f, "/proc/self/task/%d/comm", thread->tid); + pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs); + if ((fd = open(f, O_RDONLY|O_CLOEXEC)) < 0 || (len = read(fd, name, len)) < 0) status = errno; + else name[len-1] = 0; + /* remove trailing new line only if successful*/ + /*It seems that Linux indeed always adds a newline, so removing it + unconditionally seems fine.*/ + + if (fd >= 0) close(fd); + pthread_setcancelstate(cs, 0); + return status; +} \ No newline at end of file