1 /* $OpenBSD: earlysig.c,v 1.2 2014/05/20 01:25:24 guenther Exp $ */
2
3 /*
4 * Public domain. 2005, Otto Moerbeek; 2013, Philip Guenther
5 *
6 * Try to create the case where a signal is delivered to a process before
7 * the pthread fork() wrapper can unlock the ld.so bind lock.
8 */
9
10 #include <sys/types.h>
11 #include <sys/time.h>
12 #include <sys/utsname.h>
13 #include <sys/wait.h>
14
15 #include <err.h>
16 #include <pthread.h>
17 #include <signal.h>
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <string.h>
21 #include <unistd.h>
22
dohup(int signo)23 void dohup(int signo)
24 {
25 struct utsname name;
26 uname(&name); /* anything that'll require binding */
27 }
28
tmain(void * arg)29 void *tmain(void *arg)
30 {
31 return (arg);
32 }
33
34 int
main()35 main()
36 {
37 pthread_t tid;
38 pid_t pid, rpid;
39 int r, status;
40
41 if (signal(SIGHUP, dohup) == SIG_ERR)
42 err(1, "signal");
43
44 /* make sure the thread library is fully active */
45 if ((r = pthread_create(&tid, NULL, tmain, NULL)))
46 errc(1, r, "pthread_create");
47 pthread_join(tid, NULL);
48
49 /* make sure kill() and all the symbols in fork() are bound */
50 kill(0, 0);
51 if ((pid = fork()) <= 0) {
52 if (pid == -1)
53 err(1, "fork");
54 _exit(0);
55 }
56 if (waitpid(pid, &status, 0) == -1)
57 err(1, "waitpid");
58
59
60 switch(pid = fork()) {
61 case -1:
62 err(1, "fork");
63 break;
64 case 0:
65 sleep(2);
66 _exit(0);
67 default:
68 kill(pid, SIGHUP);
69 sleep(3);
70 if ((rpid = waitpid(pid, &status, WNOHANG)) == -1)
71 err(1, "waitpid");
72 if (rpid == 0) {
73 /* took too long */
74 kill(pid, SIGKILL);
75 if (waitpid(pid, &status, 0) == -1)
76 err(1, "waitpid");
77 }
78 if (WIFEXITED(status) && WEXITSTATUS(status) == 0)
79 exit(0);
80 else if (WIFEXITED(status))
81 errx(1, "child exited with status %d",
82 WEXITSTATUS(status));
83 else if (WTERMSIG(status) == SIGKILL)
84 errx(1, "failed: child hung");
85 errx(1, "child killed by signal %d", WTERMSIG(status));
86 }
87 }
88