diff options
author | Philip Guenther <guenther@cvs.openbsd.org> | 2013-06-21 06:47:21 +0000 |
---|---|---|
committer | Philip Guenther <guenther@cvs.openbsd.org> | 2013-06-21 06:47:21 +0000 |
commit | 9fd81a0e33aa45db36dc88769d12aef5c6d75fc8 (patch) | |
tree | fb7ab180e88a35d3f3e2913ca3e956546c722601 | |
parent | 18f0593eba6ee930bb1ad9ad4c452fb8a7fb1bbd (diff) |
Add earlysig test to check whether the pthread fork() wrapper
has a critical section where getting a signal causes a hang. Based on
otto@ earlysig kernel regress; suggested by miod@
-rw-r--r-- | regress/lib/libpthread/Makefile | 5 | ||||
-rw-r--r-- | regress/lib/libpthread/earlysig/Makefile | 5 | ||||
-rw-r--r-- | regress/lib/libpthread/earlysig/earlysig.c | 87 |
3 files changed, 95 insertions, 2 deletions
diff --git a/regress/lib/libpthread/Makefile b/regress/lib/libpthread/Makefile index 2cdd9958cb0..9358149c4d3 100644 --- a/regress/lib/libpthread/Makefile +++ b/regress/lib/libpthread/Makefile @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile,v 1.42 2013/03/25 08:03:18 guenther Exp $ +# $OpenBSD: Makefile,v 1.43 2013/06/21 06:47:20 guenther Exp $ # disabled because it requires a buggy behavior that uthread had: # dup2_race @@ -12,7 +12,8 @@ # blocked_fifo SUBDIR= barrier blocked_shutdown \ - cancel cancel2 close close_race closefrom cwd errno execve fork \ + cancel cancel2 close close_race closefrom cwd earlysig \ + errno execve fork \ group malloc_duel netdb pcap poll preemption preemption_float \ pthread_atfork pthread_cond_timedwait pthread_create \ pthread_join pthread_kill pthread_mutex \ diff --git a/regress/lib/libpthread/earlysig/Makefile b/regress/lib/libpthread/earlysig/Makefile new file mode 100644 index 00000000000..f18ead884e9 --- /dev/null +++ b/regress/lib/libpthread/earlysig/Makefile @@ -0,0 +1,5 @@ +# $OpenBSD: Makefile,v 1.1 2013/06/21 06:47:20 guenther Exp $ + +PROG= earlysig + +.include <bsd.regress.mk> diff --git a/regress/lib/libpthread/earlysig/earlysig.c b/regress/lib/libpthread/earlysig/earlysig.c new file mode 100644 index 00000000000..e65caaad53f --- /dev/null +++ b/regress/lib/libpthread/earlysig/earlysig.c @@ -0,0 +1,87 @@ +/* $OpenBSD: earlysig.c,v 1.1 2013/06/21 06:47:20 guenther Exp $ */ + +/* + * Public domain. 2005, Otto Moerbeek; 2013, Philip Guenther + * + * Try to create the case where a signal is delivered to a process before + * the pthread fork() wrapper can unlock the ld.so bind lock. + */ + +#include <sys/types.h> +#include <sys/time.h> +#include <sys/utsname.h> +#include <sys/wait.h> + +#include <err.h> +#include <pthread.h> +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +void dohup(int signo) +{ + struct utsname name; + uname(&name); /* anything that'll require binding */ +} + +void *tmain(void *arg) +{ + return (arg); +} + +int +main() +{ + pthread_t tid; + pid_t pid, rpid; + int r, status; + + if (signal(SIGHUP, dohup) == SIG_ERR) + err(1, "signal"); + + /* make sure the thread library is fully active */ + if ((r = pthread_create(&tid, NULL, tmain, NULL))) + errx(1, "pthread_create: %s", strerror(r)); + pthread_join(tid, NULL); + + /* make sure kill() and all the symbols in fork() are bound */ + kill(0, 0); + if ((pid = fork()) <= 0) { + if (pid == -1) + err(1, "fork"); + _exit(0); + } + if (waitpid(pid, &status, 0) == -1) + err(1, "waitpid"); + + + switch(pid = fork()) { + case -1: + err(1, "fork"); + break; + case 0: + sleep(2); + _exit(0); + default: + kill(pid, SIGHUP); + sleep(3); + if ((rpid = waitpid(pid, &status, WNOHANG)) == -1) + err(1, "waitpid"); + if (rpid == 0) { + /* took too long */ + kill(pid, SIGKILL); + if (waitpid(pid, &status, 0) == -1) + err(1, "waitpid"); + } + if (WIFEXITED(status) && WEXITSTATUS(status) == 0) + exit(0); + else if (WIFEXITED(status)) + errx(1, "child exited with status %d", + WEXITSTATUS(status)); + else if (WTERMSIG(status) == SIGKILL) + errx(1, "failed: child hung"); + errx(1, "child killed by signal %d", WTERMSIG(status)); + } +} |