aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2011-11-26 14:52:20 +0000
committerChristian Grothoff <christian@grothoff.org>2011-11-26 14:52:20 +0000
commit438d1dd06f683f424c4c9958918778804c9f5519 (patch)
tree73db20ad5bd8b319e5edacffd7e3a9541794cbc3 /src
parentfe11f7d1a91c329acf601b9dde873199cd5c876b (diff)
downloadgnunet-438d1dd06f683f424c4c9958918778804c9f5519.tar.gz
gnunet-438d1dd06f683f424c4c9958918778804c9f5519.zip
Implementing Thomas Bushnell's suggestion to work around the signal race without needing special vfork semantics
Diffstat (limited to 'src')
-rw-r--r--src/util/os_priority.c35
-rw-r--r--src/util/scheduler.c10
2 files changed, 10 insertions, 35 deletions
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,
595 &fd_stdin_write, sizeof (int)); 595 &fd_stdin_write, sizeof (int));
596 } 596 }
597 597
598#if HAVE_WORKING_VFORK
599 ret = vfork ();
600#else
601 ret = fork (); 598 ret = fork ();
602#endif
603 if (ret != 0) 599 if (ret != 0)
604 { 600 {
605 if (ret == -1) 601 if (ret == -1)
@@ -611,22 +607,6 @@ GNUNET_OS_start_process_va (struct GNUNET_DISK_PipeHandle *pipe_stdin,
611 } 607 }
612 else 608 else
613 { 609 {
614
615#if HAVE_WORKING_VFORK
616 /* let's hope vfork actually works; for some extreme cases (including
617 * a testcase) we need 'execvp' to have run before we return, since
618 * we may send a signal to the process next and we don't want it
619 * to be caught by OUR signal handler (but either by the default
620 * handler or the actual handler as installed by the process itself). */
621#else
622 /* let's give the child process a chance to run execvp, 1s should
623 * be plenty in practice */
624 if (pipe_stdout != NULL)
625 GNUNET_DISK_pipe_close_end (pipe_stdout, GNUNET_DISK_PIPE_END_WRITE);
626 if (pipe_stdin != NULL)
627 GNUNET_DISK_pipe_close_end (pipe_stdin, GNUNET_DISK_PIPE_END_READ);
628 sleep (1);
629#endif
630 gnunet_proc = GNUNET_malloc (sizeof (struct GNUNET_OS_Process)); 610 gnunet_proc = GNUNET_malloc (sizeof (struct GNUNET_OS_Process));
631 gnunet_proc->pid = ret; 611 gnunet_proc->pid = ret;
632#if ENABLE_WINDOWS_WORKAROUNDS 612#if ENABLE_WINDOWS_WORKAROUNDS
@@ -906,11 +886,7 @@ GNUNET_OS_start_process_v (const int *lsocks, const char *filename,
906 GNUNET_array_append (lscp, ls, k); 886 GNUNET_array_append (lscp, ls, k);
907 GNUNET_array_append (lscp, ls, -1); 887 GNUNET_array_append (lscp, ls, -1);
908 } 888 }
909#if HAVE_WORKING_VFORK
910 ret = vfork ();
911#else
912 ret = fork (); 889 ret = fork ();
913#endif
914 if (ret != 0) 890 if (ret != 0)
915 { 891 {
916 if (ret == -1) 892 if (ret == -1)
@@ -922,17 +898,6 @@ GNUNET_OS_start_process_v (const int *lsocks, const char *filename,
922 } 898 }
923 else 899 else
924 { 900 {
925#if HAVE_WORKING_VFORK
926 /* let's hope vfork actually works; for some extreme cases (including
927 * a testcase) we need 'execvp' to have run before we return, since
928 * we may send a signal to the process next and we don't want it
929 * to be caught by OUR signal handler (but either by the default
930 * handler or the actual handler as installed by the process itself). */
931#else
932 /* let's give the child process a chance to run execvp, 1s should
933 * be plenty in practice */
934 sleep (1);
935#endif
936 gnunet_proc = GNUNET_malloc (sizeof (struct GNUNET_OS_Process)); 901 gnunet_proc = GNUNET_malloc (sizeof (struct GNUNET_OS_Process));
937 gnunet_proc->pid = ret; 902 gnunet_proc->pid = ret;
938#if ENABLE_WINDOWS_WORKAROUNDS 903#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
@@ -702,6 +702,12 @@ run_ready (struct GNUNET_NETWORK_FDSet *rs, struct GNUNET_NETWORK_FDSet *ws)
702static struct GNUNET_DISK_PipeHandle *shutdown_pipe_handle; 702static struct GNUNET_DISK_PipeHandle *shutdown_pipe_handle;
703 703
704/** 704/**
705 * Process ID of this process at the time we installed the various
706 * signal handlers.
707 */
708static pid_t my_pid;
709
710/**
705 * Signal handler called for SIGPIPE. 711 * Signal handler called for SIGPIPE.
706 */ 712 */
707#ifndef MINGW 713#ifndef MINGW
@@ -720,6 +726,9 @@ sighandler_shutdown ()
720 static char c; 726 static char c;
721 int old_errno = errno; /* backup errno */ 727 int old_errno = errno; /* backup errno */
722 728
729 if (getpid() != my_pid)
730 exit(1); /* we have fork'ed since the signal handler was created,
731 ignore the signal, see https://gnunet.org/vfork discussion */
723 GNUNET_DISK_file_write (GNUNET_DISK_pipe_handle 732 GNUNET_DISK_file_write (GNUNET_DISK_pipe_handle
724 (shutdown_pipe_handle, GNUNET_DISK_PIPE_END_WRITE), 733 (shutdown_pipe_handle, GNUNET_DISK_PIPE_END_WRITE),
725 &c, sizeof (c)); 734 &c, sizeof (c));
@@ -799,6 +808,7 @@ GNUNET_SCHEDULER_run (GNUNET_SCHEDULER_Task task, void *task_cls)
799 pr = GNUNET_DISK_pipe_handle (shutdown_pipe_handle, 808 pr = GNUNET_DISK_pipe_handle (shutdown_pipe_handle,
800 GNUNET_DISK_PIPE_END_READ); 809 GNUNET_DISK_PIPE_END_READ);
801 GNUNET_assert (pr != NULL); 810 GNUNET_assert (pr != NULL);
811 my_pid = getpid ();
802 shc_int = GNUNET_SIGNAL_handler_install (SIGINT, &sighandler_shutdown); 812 shc_int = GNUNET_SIGNAL_handler_install (SIGINT, &sighandler_shutdown);
803 shc_term = GNUNET_SIGNAL_handler_install (SIGTERM, &sighandler_shutdown); 813 shc_term = GNUNET_SIGNAL_handler_install (SIGTERM, &sighandler_shutdown);
804#ifndef MINGW 814#ifndef MINGW