1 /* $OpenBSD: cancel_wait.c,v 1.2 2015/09/14 08:36:32 guenther Exp $ */
2 /* PUBLIC DOMAIN <marc@snafu.org> */
3 
4 /*
5  * Check that a thread waiting in wait/waitpid/wait3/wait4 can be
6  * cancelled.
7  */
8 
9 #include <sys/types.h>
10 #include <sys/resource.h>
11 #include <sys/time.h>
12 #include <sys/wait.h>
13 
14 #include <err.h>
15 #include <pthread.h>
16 #include <unistd.h>
17 
18 #include "test.h"
19 
20 pid_t child;
21 int status;
22 
23 static void *
wait_thread(void * arg)24 wait_thread(void *arg)
25 {
26 	wait(&status);
27 	return (arg);
28 }
29 
30 static void *
waitpid_thread(void * arg)31 waitpid_thread(void *arg)
32 {
33 	waitpid(child, &status, 0);
34 	return (arg);
35 }
36 
37 static void *
wait3_thread(void * arg)38 wait3_thread(void *arg)
39 {
40 	wait3(&status, 0, NULL);
41 	return (arg);
42 }
43 
44 static void *
wait4_thread(void * arg)45 wait4_thread(void *arg)
46 {
47 	wait4(child, &status, 0, NULL);
48 	return (arg);
49 }
50 
51 int
main(int argc,char * argv[])52 main(int argc, char *argv[])
53 {
54 	pthread_t thread;
55 	void *ret = NULL;
56 
57 	child = fork();
58 	if (child == -1)
59 		err(1, "fork");
60 	if (child == 0) {
61 		sleep(1000000);
62 		_exit(0);
63 	}
64 
65 	status = 42;
66 
67 	printf("trying wait\n");
68 	CHECKr(pthread_create(&thread, NULL, wait_thread, NULL));
69 	sleep(1);
70 	CHECKr(pthread_cancel(thread));
71 	CHECKr(pthread_join(thread, &ret));
72 	ASSERT(ret == PTHREAD_CANCELED);
73 	ASSERT(status == 42);
74 
75 	printf("trying waitpid\n");
76 	CHECKr(pthread_create(&thread, NULL, waitpid_thread, NULL));
77 	sleep(1);
78 	CHECKr(pthread_cancel(thread));
79 	CHECKr(pthread_join(thread, &ret));
80 	ASSERT(ret == PTHREAD_CANCELED);
81 	ASSERT(status == 42);
82 
83 	printf("trying wait3\n");
84 	CHECKr(pthread_create(&thread, NULL, wait3_thread, NULL));
85 	sleep(1);
86 	CHECKr(pthread_cancel(thread));
87 	CHECKr(pthread_join(thread, &ret));
88 	ASSERT(ret == PTHREAD_CANCELED);
89 	ASSERT(status == 42);
90 
91 	printf("trying wait4\n");
92 	CHECKr(pthread_create(&thread, NULL, wait4_thread, NULL));
93 	sleep(1);
94 	CHECKr(pthread_cancel(thread));
95 	CHECKr(pthread_join(thread, &ret));
96 	ASSERT(ret == PTHREAD_CANCELED);
97 	ASSERT(status == 42);
98 
99 	kill(child, SIGKILL);
100 
101 	CHECKr(pthread_create(&thread, NULL, wait4_thread, NULL));
102 	sleep(1);
103 	CHECKr(pthread_join(thread, &ret));
104 	ASSERT(ret == NULL);
105 	ASSERT(WIFSIGNALED(status));
106 	ASSERT(WTERMSIG(status) == 9);
107 
108 	SUCCEED;
109 }
110