• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // commit: fb11b6b85e1e01daf17228be32d7f98b47517363 2011-02-19
2 // pthread_exit should call dtors (even in the last thread)
3 #include <stdlib.h>
4 #include <string.h>
5 #include <errno.h>
6 #include <pthread.h>
7 #include <sys/wait.h>
8 #include <unistd.h>
9 #include "test.h"
10 
11 #define TEST(r, f) if (((r)=(f))) t_error(#f " failed: %s\n", strerror(r))
12 #define TESTC(c, m) ( (c) || (t_error("%s failed (" m ")\n", #c), 0) )
13 
14 static pthread_key_t k;
15 static int data;
16 
dtor(void * p)17 static void dtor(void *p)
18 {
19 	*(int *)p = 1;
20 }
21 
start(void * arg)22 static void *start(void *arg)
23 {
24 	if (pthread_setspecific(k, arg))
25 		return arg;
26 	return 0;
27 }
28 
cleanup(void)29 static void cleanup(void)
30 {
31 	TESTC(data == 1, "dtor was not run for the last thread");
32 	_exit(t_status);
33 }
34 
die(void)35 static void die(void)
36 {
37 	_exit(1);
38 }
39 
main(void)40 int main(void)
41 {
42 	pthread_t td;
43 	int r, arg=0, pid;
44 	void *res;
45 
46 	// test if atexit handlers are run after pthread_exit
47 	// (early musl failed this test)
48 	pid = fork();
49 	switch (pid) {
50 	case -1:
51 		t_error("fork failed: %s\n", strerror(errno));
52 		return 1;
53 	case 0:
54 		atexit(die);
55 		pthread_exit(0);
56 	default:
57 		if (waitpid(pid, &r, 0) != pid) {
58 			t_error("waitpid failed: %s\n", strerror(errno));
59 			return 1;
60 		}
61 		if (!WIFEXITED(r) || WEXITSTATUS(r) != 1) {
62 			t_error("atexit handler was not run after last thread exited"
63 				" (exited=%d, signal=%d, status=%d, want exit status=1)\n",
64 				WIFEXITED(r), !WIFEXITED(r)&&WIFSIGNALED(r)?WTERMSIG(r):0, WIFEXITED(r)?WEXITSTATUS(r):0);
65 			return 1;
66 		}
67 	}
68 
69 	// dtor should set tsd (arg and data) from 0 to 1
70 	if (atexit(cleanup)) {
71 		t_error("atexit failed\n");
72 		return 1;
73 	}
74 	TEST(r, pthread_key_create(&k, dtor));
75 	TEST(r, pthread_setspecific(k, &data));
76 	TEST(r, pthread_create(&td, 0, start, &arg));
77 	TEST(r, pthread_join(td, &res));
78 	TESTC(res == 0, "pthread_setspecific failed in thread");
79 	TESTC(arg == 1, "dtor failed to run");
80 	TESTC(data == 0, "tsd in main thread is corrupted");
81 	TESTC(pthread_getspecific(k) == &data, "tsd in main thread is corrupted");
82 	pthread_exit(0);
83 }
84