diff options
author | Christian Grothoff <christian@grothoff.org> | 2011-11-26 14:52:20 +0000 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2011-11-26 14:52:20 +0000 |
commit | 438d1dd06f683f424c4c9958918778804c9f5519 (patch) | |
tree | 73db20ad5bd8b319e5edacffd7e3a9541794cbc3 /src | |
parent | fe11f7d1a91c329acf601b9dde873199cd5c876b (diff) | |
download | gnunet-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.c | 35 | ||||
-rw-r--r-- | src/util/scheduler.c | 10 |
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) | |||
702 | static struct GNUNET_DISK_PipeHandle *shutdown_pipe_handle; | 702 | static 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 | */ | ||
708 | static 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 |