/* * This file and its contents are supplied under the terms of the * Common Development and Distribution License ("CDDL"), version 1.0. * You may only use this file in accordance with the terms of version * 1.0 of the CDDL. * * A full copy of the text of the CDDL should have accompanied this * source. A copy of the CDDL is also available via the Internet at * http://www.illumos.org/license/CDDL. */ /* * Copyright 2018 Joyent, Inc. */ /* * Some basic pthread name API tests. */ #include #include #include #include #include #include #include #include #include #include #include /*ARGSUSED*/ static void * thr(void *unused) { (void) sleep(100); return (NULL); } /*ARGSUSED*/ int main(int argc, char *argv[]) { char name[PTHREAD_MAX_NAMELEN_NP]; pthread_attr_t attr; char path[PATH_MAX]; pthread_t tid; ssize_t n; int test; int rc; int fd; /* Default thread name is empty string. */ test = 1; rc = pthread_getname_np(pthread_self(), name, sizeof (name)); if (rc != 0 || strcmp(name, "") != 0) errx(EXIT_FAILURE, "test %d failed with %d", test, rc); /* Can set name. */ test = 2; (void) strlcpy(name, "main", sizeof (name)); rc = pthread_setname_np(pthread_self(), name); if (rc != 0) errx(EXIT_FAILURE, "test %d failed with %d", test, rc); rc = pthread_getname_np(pthread_self(), name, sizeof (name)); if (rc != 0 || strcmp(name, "main") != 0) errx(EXIT_FAILURE, "test %d failed with %d", test, rc); /* ERANGE check. */ test = 3; rc = pthread_getname_np(pthread_self(), name, 2); if (rc != ERANGE) errx(EXIT_FAILURE, "test %d failed with %d", test, rc); /* EINVAL check. */ test = 4; rc = pthread_getname_np(pthread_self(), NULL, sizeof (name)); if (rc != EINVAL) errx(EXIT_FAILURE, "test %d failed with %d", test, rc); /* can clear thread name. */ test = 5; rc = pthread_setname_np(pthread_self(), NULL); if (rc != 0) errx(EXIT_FAILURE, "test %d failed with %d", test, rc); rc = pthread_getname_np(pthread_self(), name, sizeof (name)); if (rc != 0 || strcmp(name, "") != 0) errx(EXIT_FAILURE, "test %d failed with %d", test, rc); /* non-existent thread check. */ test = 6; rc = pthread_getname_np(808, name, sizeof (name)); if (rc != ESRCH) errx(EXIT_FAILURE, "test %d failed with %d", test, rc); rc = pthread_setname_np(808, "state"); if (rc != ESRCH) errx(EXIT_FAILURE, "test %d failed with %d", test, rc); /* too long a name. */ test = 7; rc = pthread_setname_np(pthread_self(), "12345678901234567890123456789012"); if (rc != ERANGE) errx(EXIT_FAILURE, "test %d failed with %d", test, rc); /* can name another thread. */ test = 8; rc = pthread_create(&tid, NULL, thr, NULL); if (rc != 0) errx(EXIT_FAILURE, "test %d failed with %d", test, rc); rc = pthread_setname_np(tid, "otherthread"); if (rc != 0) errx(EXIT_FAILURE, "test %d failed with %d", test, rc); /* attr tests. */ test = 9; (void) pthread_attr_init(&attr); rc = pthread_attr_setname_np(&attr, "12345678901234567890123456789012"); if (rc != ERANGE) errx(EXIT_FAILURE, "test %d failed with %d", test, rc); rc = pthread_attr_setname_np(&attr, "thread2"); if (rc != 0) errx(EXIT_FAILURE, "test %d failed with %d", test, rc); rc = pthread_attr_getname_np(&attr, NULL, sizeof (name)); if (rc != EINVAL) errx(EXIT_FAILURE, "test %d failed with %d", test, rc); rc = pthread_attr_getname_np(&attr, name, 2); if (rc != ERANGE) errx(EXIT_FAILURE, "test %d failed with %d", test, rc); /* does the attr actually apply? */ test = 10; rc = pthread_create(&tid, &attr, thr, NULL); if (rc != 0) errx(EXIT_FAILURE, "test %d failed with %d", test, rc); rc = pthread_getname_np(tid, name, sizeof (name)); if (rc != 0 || strcmp(name, "thread2") != 0) errx(EXIT_FAILURE, "test %d failed with %d", test, rc); /* proc read tests */ test = 11; (void) snprintf(path, sizeof (path), "/proc/self/lwp/%d/lwpname", (int)tid); fd = open(path, O_RDWR); if (fd == -1) errx(EXIT_FAILURE, "test %d failed with %d", test, errno); n = read(fd, name, sizeof (name)); if (n != sizeof (name) || strcmp(name, "thread2") != 0) errx(EXIT_FAILURE, "test %d failed with %d", test, rc); if (lseek(fd, 0, SEEK_SET) != 0) errx(EXIT_FAILURE, "test %d failed with %d", test, errno); n = read(fd, name, PTHREAD_MAX_NAMELEN_NP * 2); if (n != sizeof (name) || strcmp(name, "thread2") != 0) errx(EXIT_FAILURE, "test %d failed with %d", test, rc); if (lseek(fd, 0, SEEK_SET) != 0) errx(EXIT_FAILURE, "test %d failed with %d", test, errno); n = read(fd, name, 4); if (n != 4 || strncmp(name, "thre", 4) != 0) errx(EXIT_FAILURE, "test %d failed with %d", test, rc); /* proc write tests */ test = 12; if (lseek(fd, 0, SEEK_SET) != 0) errx(EXIT_FAILURE, "test %d failed with %d", test, errno); n = write(fd, "1234567890123456789012345678901", PTHREAD_MAX_NAMELEN_NP); if (n != PTHREAD_MAX_NAMELEN_NP) errx(EXIT_FAILURE, "test %d failed with %d", test, errno); if (lseek(fd, 0, SEEK_SET) != 0) errx(EXIT_FAILURE, "test %d failed with %d", test, errno); n = write(fd, "foo", sizeof ("foo")); if (n != sizeof ("foo")) errx(EXIT_FAILURE, "test %d failed with %d", test, errno); if (lseek(fd, 0, SEEK_SET) != 0) errx(EXIT_FAILURE, "test %d failed with %d", test, errno); n = read(fd, name, sizeof (name)); if (n != sizeof (name) || strcmp(name, "foo") != 0) errx(EXIT_FAILURE, "test %d failed with %d", test, rc); (void) close(fd); /* thr_* API. */ test = 13; rc = thr_setname(thr_self(), "main"); if (rc != 0) errx(EXIT_FAILURE, "test %d failed with %d", test, rc); rc = thr_getname(thr_self(), name, sizeof (name)); if (rc != 0 || strcmp(name, "main") != 0) errx(EXIT_FAILURE, "test %d failed with %d", test, rc); /* badness */ test = 14; rc = thr_setname(thr_self(), "\033]0;messeduptitle\a"); if (rc != EINVAL) errx(EXIT_FAILURE, "test %d failed with %d", test, rc); rc = thr_setname(thr_self(), "ab\177\177\n"); if (rc != EINVAL) errx(EXIT_FAILURE, "test %d failed with %d", test, rc); rc = pthread_attr_setname_np(&attr, "\033]0;messeduptitle\a"); if (rc != EINVAL) errx(EXIT_FAILURE, "test %d failed with %d", test, rc); rc = pthread_attr_setname_np(&attr, "ab\177\177\n"); if (rc != EINVAL) errx(EXIT_FAILURE, "test %d failed with %d", test, rc); return (EXIT_SUCCESS); }