/* Creates several daemon threads and non-daemon threads. Tests that the process can exit even if the daemon threads are still running, as per thr_create(3C). */ #include <pthread.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <thread.h> #include <unistd.h> #define DAEMON_THREADS 5 #define NON_DAEMON_THREADS 6 #define SLEEP_100_MS usleep(100 * 1000) static pthread_barrier_t barrier; void *daemon_thread_func(void *arg) { size_t index = (size_t) arg; printf("DAEMON thread #%zu running\n", index); fflush(stdout); pthread_barrier_wait(&barrier); /* Give the non-daemon threads enough time to exit. */ sleep(10); printf("DAEMON thread #%zu still running?!\n", index); fflush(stdout); return NULL; } void *normal_thread_func(void *arg) { size_t index = (size_t) arg; printf("non-daemon thread #%zu running\n", index); fflush(stdout); pthread_barrier_wait(&barrier); sleep(2); return NULL; } int main(void) { size_t i; int ret = pthread_barrier_init(&barrier, NULL, DAEMON_THREADS + NON_DAEMON_THREADS + 1); if (ret != 0) { fprintf(stderr, "pthread_barrier_init failed: %s\n", strerror(ret)); return 1; } for (i = 0; i < DAEMON_THREADS; i++) { ret = thr_create(NULL, 0, daemon_thread_func, (void *) i, THR_DAEMON, NULL); if (ret != 0) { fprintf(stderr, "thr_create failed: %s\n", strerror(ret)); return 1; } SLEEP_100_MS; } for (i = 0; i < NON_DAEMON_THREADS; i++) { ret = thr_create(NULL, 0, normal_thread_func, (void *) i, 0, NULL); if (ret != 0) { fprintf(stderr, "thr_create failed: %s\n", strerror(ret)); return 1; } SLEEP_100_MS; } pthread_barrier_wait(&barrier); printf("MAIN thread exiting\n"); /* Exit only the main thread, not whole process. That is, do not exit(0) or return(0). */ thr_exit(NULL); }