1/* Creates several daemon threads and non-daemon threads.
2   Tests that the process can exit even if the daemon threads are still running,
3   as per thr_create(3C). */
4
5#include <pthread.h>
6#include <stdio.h>
7#include <stdlib.h>
8#include <string.h>
9#include <thread.h>
10#include <unistd.h>
11
12#define DAEMON_THREADS 5
13#define NON_DAEMON_THREADS 6
14#define SLEEP_100_MS usleep(100 * 1000)
15
16static pthread_barrier_t barrier;
17
18void *daemon_thread_func(void *arg) {
19   size_t index = (size_t) arg;
20   printf("DAEMON thread #%zu running\n", index); fflush(stdout);
21   pthread_barrier_wait(&barrier);
22
23   /* Give the non-daemon threads enough time to exit. */
24   sleep(10);
25   printf("DAEMON thread #%zu still running?!\n", index); fflush(stdout);
26   return NULL;
27}
28
29void *normal_thread_func(void *arg) {
30   size_t index = (size_t) arg;
31   printf("non-daemon thread #%zu running\n", index); fflush(stdout);
32   pthread_barrier_wait(&barrier);
33
34   sleep(2);
35   return NULL;
36}
37
38int main(void) {
39   size_t i;
40   int ret = pthread_barrier_init(&barrier, NULL,
41                                  DAEMON_THREADS + NON_DAEMON_THREADS + 1);
42   if (ret != 0) {
43      fprintf(stderr, "pthread_barrier_init failed: %s\n", strerror(ret));
44      return 1;
45   }
46
47   for (i = 0; i < DAEMON_THREADS; i++) {
48      ret = thr_create(NULL, 0, daemon_thread_func, (void *) i,
49                       THR_DAEMON, NULL);
50      if (ret != 0) {
51         fprintf(stderr, "thr_create failed: %s\n", strerror(ret));
52         return 1;
53      }
54      SLEEP_100_MS;
55   }
56
57   for (i = 0; i < NON_DAEMON_THREADS; i++) {
58      ret = thr_create(NULL, 0, normal_thread_func, (void *) i, 0, NULL);
59      if (ret != 0) {
60         fprintf(stderr, "thr_create failed: %s\n", strerror(ret));
61         return 1;
62      }
63      SLEEP_100_MS;
64   }
65
66   pthread_barrier_wait(&barrier);
67
68   printf("MAIN thread exiting\n");
69   /* Exit only the main thread, not whole process.
70      That is, do not exit(0) or return(0). */
71   thr_exit(NULL);
72}
73