1*5ad04d35Sguenther /* $OpenBSD: earlysig.c,v 1.2 2014/05/20 01:25:24 guenther Exp $ */
20df5e8aeSguenther
30df5e8aeSguenther /*
40df5e8aeSguenther * Public domain. 2005, Otto Moerbeek; 2013, Philip Guenther
50df5e8aeSguenther *
60df5e8aeSguenther * Try to create the case where a signal is delivered to a process before
70df5e8aeSguenther * the pthread fork() wrapper can unlock the ld.so bind lock.
80df5e8aeSguenther */
90df5e8aeSguenther
100df5e8aeSguenther #include <sys/types.h>
110df5e8aeSguenther #include <sys/time.h>
120df5e8aeSguenther #include <sys/utsname.h>
130df5e8aeSguenther #include <sys/wait.h>
140df5e8aeSguenther
150df5e8aeSguenther #include <err.h>
160df5e8aeSguenther #include <pthread.h>
170df5e8aeSguenther #include <signal.h>
180df5e8aeSguenther #include <stdio.h>
190df5e8aeSguenther #include <stdlib.h>
200df5e8aeSguenther #include <string.h>
210df5e8aeSguenther #include <unistd.h>
220df5e8aeSguenther
dohup(int signo)230df5e8aeSguenther void dohup(int signo)
240df5e8aeSguenther {
250df5e8aeSguenther struct utsname name;
260df5e8aeSguenther uname(&name); /* anything that'll require binding */
270df5e8aeSguenther }
280df5e8aeSguenther
tmain(void * arg)290df5e8aeSguenther void *tmain(void *arg)
300df5e8aeSguenther {
310df5e8aeSguenther return (arg);
320df5e8aeSguenther }
330df5e8aeSguenther
340df5e8aeSguenther int
main()350df5e8aeSguenther main()
360df5e8aeSguenther {
370df5e8aeSguenther pthread_t tid;
380df5e8aeSguenther pid_t pid, rpid;
390df5e8aeSguenther int r, status;
400df5e8aeSguenther
410df5e8aeSguenther if (signal(SIGHUP, dohup) == SIG_ERR)
420df5e8aeSguenther err(1, "signal");
430df5e8aeSguenther
440df5e8aeSguenther /* make sure the thread library is fully active */
450df5e8aeSguenther if ((r = pthread_create(&tid, NULL, tmain, NULL)))
46*5ad04d35Sguenther errc(1, r, "pthread_create");
470df5e8aeSguenther pthread_join(tid, NULL);
480df5e8aeSguenther
490df5e8aeSguenther /* make sure kill() and all the symbols in fork() are bound */
500df5e8aeSguenther kill(0, 0);
510df5e8aeSguenther if ((pid = fork()) <= 0) {
520df5e8aeSguenther if (pid == -1)
530df5e8aeSguenther err(1, "fork");
540df5e8aeSguenther _exit(0);
550df5e8aeSguenther }
560df5e8aeSguenther if (waitpid(pid, &status, 0) == -1)
570df5e8aeSguenther err(1, "waitpid");
580df5e8aeSguenther
590df5e8aeSguenther
600df5e8aeSguenther switch(pid = fork()) {
610df5e8aeSguenther case -1:
620df5e8aeSguenther err(1, "fork");
630df5e8aeSguenther break;
640df5e8aeSguenther case 0:
650df5e8aeSguenther sleep(2);
660df5e8aeSguenther _exit(0);
670df5e8aeSguenther default:
680df5e8aeSguenther kill(pid, SIGHUP);
690df5e8aeSguenther sleep(3);
700df5e8aeSguenther if ((rpid = waitpid(pid, &status, WNOHANG)) == -1)
710df5e8aeSguenther err(1, "waitpid");
720df5e8aeSguenther if (rpid == 0) {
730df5e8aeSguenther /* took too long */
740df5e8aeSguenther kill(pid, SIGKILL);
750df5e8aeSguenther if (waitpid(pid, &status, 0) == -1)
760df5e8aeSguenther err(1, "waitpid");
770df5e8aeSguenther }
780df5e8aeSguenther if (WIFEXITED(status) && WEXITSTATUS(status) == 0)
790df5e8aeSguenther exit(0);
800df5e8aeSguenther else if (WIFEXITED(status))
810df5e8aeSguenther errx(1, "child exited with status %d",
820df5e8aeSguenther WEXITSTATUS(status));
830df5e8aeSguenther else if (WTERMSIG(status) == SIGKILL)
840df5e8aeSguenther errx(1, "failed: child hung");
850df5e8aeSguenther errx(1, "child killed by signal %d", WTERMSIG(status));
860df5e8aeSguenther }
870df5e8aeSguenther }
88