From 438d1dd06f683f424c4c9958918778804c9f5519 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sat, 26 Nov 2011 14:52:20 +0000 Subject: Implementing Thomas Bushnell's suggestion to work around the signal race without needing special vfork semantics --- src/util/os_priority.c | 35 ----------------------------------- src/util/scheduler.c | 10 ++++++++++ 2 files changed, 10 insertions(+), 35 deletions(-) (limited to 'src') diff --git a/src/util/os_priority.c b/src/util/os_priority.c index a7ce0c5e5..3b3b022b9 100644 --- a/src/util/os_priority.c +++ b/src/util/os_priority.c @@ -595,11 +595,7 @@ GNUNET_OS_start_process_va (struct GNUNET_DISK_PipeHandle *pipe_stdin, &fd_stdin_write, sizeof (int)); } -#if HAVE_WORKING_VFORK - ret = vfork (); -#else ret = fork (); -#endif if (ret != 0) { if (ret == -1) @@ -611,22 +607,6 @@ GNUNET_OS_start_process_va (struct GNUNET_DISK_PipeHandle *pipe_stdin, } else { - -#if HAVE_WORKING_VFORK - /* let's hope vfork actually works; for some extreme cases (including - * a testcase) we need 'execvp' to have run before we return, since - * we may send a signal to the process next and we don't want it - * to be caught by OUR signal handler (but either by the default - * handler or the actual handler as installed by the process itself). */ -#else - /* let's give the child process a chance to run execvp, 1s should - * be plenty in practice */ - if (pipe_stdout != NULL) - GNUNET_DISK_pipe_close_end (pipe_stdout, GNUNET_DISK_PIPE_END_WRITE); - if (pipe_stdin != NULL) - GNUNET_DISK_pipe_close_end (pipe_stdin, GNUNET_DISK_PIPE_END_READ); - sleep (1); -#endif gnunet_proc = GNUNET_malloc (sizeof (struct GNUNET_OS_Process)); gnunet_proc->pid = ret; #if ENABLE_WINDOWS_WORKAROUNDS @@ -906,11 +886,7 @@ GNUNET_OS_start_process_v (const int *lsocks, const char *filename, GNUNET_array_append (lscp, ls, k); GNUNET_array_append (lscp, ls, -1); } -#if HAVE_WORKING_VFORK - ret = vfork (); -#else ret = fork (); -#endif if (ret != 0) { if (ret == -1) @@ -922,17 +898,6 @@ GNUNET_OS_start_process_v (const int *lsocks, const char *filename, } else { -#if HAVE_WORKING_VFORK - /* let's hope vfork actually works; for some extreme cases (including - * a testcase) we need 'execvp' to have run before we return, since - * we may send a signal to the process next and we don't want it - * to be caught by OUR signal handler (but either by the default - * handler or the actual handler as installed by the process itself). */ -#else - /* let's give the child process a chance to run execvp, 1s should - * be plenty in practice */ - sleep (1); -#endif gnunet_proc = GNUNET_malloc (sizeof (struct GNUNET_OS_Process)); gnunet_proc->pid = ret; #if ENABLE_WINDOWS_WORKAROUNDS diff --git a/src/util/scheduler.c b/src/util/scheduler.c index 7254b1700..d4a11fc8a 100644 --- a/src/util/scheduler.c +++ b/src/util/scheduler.c @@ -701,6 +701,12 @@ run_ready (struct GNUNET_NETWORK_FDSet *rs, struct GNUNET_NETWORK_FDSet *ws) */ static struct GNUNET_DISK_PipeHandle *shutdown_pipe_handle; +/** + * Process ID of this process at the time we installed the various + * signal handlers. + */ +static pid_t my_pid; + /** * Signal handler called for SIGPIPE. */ @@ -720,6 +726,9 @@ sighandler_shutdown () static char c; int old_errno = errno; /* backup errno */ + if (getpid() != my_pid) + exit(1); /* we have fork'ed since the signal handler was created, + ignore the signal, see https://gnunet.org/vfork discussion */ GNUNET_DISK_file_write (GNUNET_DISK_pipe_handle (shutdown_pipe_handle, GNUNET_DISK_PIPE_END_WRITE), &c, sizeof (c)); @@ -799,6 +808,7 @@ GNUNET_SCHEDULER_run (GNUNET_SCHEDULER_Task task, void *task_cls) pr = GNUNET_DISK_pipe_handle (shutdown_pipe_handle, GNUNET_DISK_PIPE_END_READ); GNUNET_assert (pr != NULL); + my_pid = getpid (); shc_int = GNUNET_SIGNAL_handler_install (SIGINT, &sighandler_shutdown); shc_term = GNUNET_SIGNAL_handler_install (SIGTERM, &sighandler_shutdown); #ifndef MINGW -- cgit v1.2.3