From 438d1dd06f683f424c4c9958918778804c9f5519 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sat, 26 Nov 2011 14:52:20 +0000 Subject: [PATCH] Implementing Thomas Bushnell's suggestion to work around the signal race without needing special vfork semantics --- configure.ac | 1 - src/util/os_priority.c | 35 ----------------------------------- src/util/scheduler.c | 10 ++++++++++ 3 files changed, 10 insertions(+), 36 deletions(-) diff --git a/configure.ac b/configure.ac index 9f00d10ed..8fc49aadc 100644 --- a/configure.ac +++ b/configure.ac @@ -613,7 +613,6 @@ AC_CHECK_MEMBER([struct sockaddr_in.sin_len], # Checks for library functions. AC_FUNC_CLOSEDIR_VOID AC_FUNC_FORK -AC_FUNC_VFORK AC_PROG_GCC_TRADITIONAL AC_FUNC_MEMCMP AC_FUNC_SELECT_ARGTYPES 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 -- 2.25.1