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 23 void dohup(int signo) 24 { 25 struct utsname name; 26 uname(&name); /* anything that'll require binding */ 27 } 28 29 void *tmain(void *arg) 30 { 31 return (arg); 32 } 33 34 int 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