diff options
author | Ludovic Courtès <ludo@gnu.org> | 2021-05-08 21:39:15 +0200 |
---|---|---|
committer | Ludovic Courtès <ludo@gnu.org> | 2021-05-08 21:39:15 +0200 |
commit | 381291f5ff4480afbb197bf5e5a2272cfe54a386 (patch) | |
tree | 31ba38ab2f583db9db457a54f801b638d43d7400 /libguile/posix.c | |
parent | 5a281e35f4a5ae78fbcf10591d9358bec8f0bee0 (diff) | |
download | guile-381291f5ff4480afbb197bf5e5a2272cfe54a386.tar.gz |
'primitive-fork' closes and recreates the current thread's 'sleep_pipe'.
Partly fixes <https://bugs.gnu.org/41948>.
Previously, the child process could end up using the same 'sleep_pipe'
as its parent, leading to a race condition handling signals.
* libguile/posix.c (do_fork): New function.
(scm_fork): Call 'do_fork' via 'scm_without_guile'.
* test-suite/standalone/test-signal-fork: New test.
* test-suite/standalone/Makefile.am (check_SCRIPTS, TESTS): Add it.
Diffstat (limited to 'libguile/posix.c')
-rw-r--r-- | libguile/posix.c | 29 |
1 files changed, 28 insertions, 1 deletions
diff --git a/libguile/posix.c b/libguile/posix.c index eaf12de32..31c4ab192 100644 --- a/libguile/posix.c +++ b/libguile/posix.c @@ -1217,6 +1217,31 @@ SCM_DEFINE (scm_execle, "execle", 2, 0, 1, #undef FUNC_NAME #ifdef HAVE_FORK + +/* Create a process and perform post-fork cleanups in the child. */ +static void * +do_fork (void *ret) +{ + pid_t pid = fork (); + + if (pid == 0) + { + /* The child process must not share its sleep pipe with the + parent. Close it and create a new one. */ + int err; + scm_thread *t = SCM_I_CURRENT_THREAD; + + close (t->sleep_pipe[0]); + close (t->sleep_pipe[1]); + err = pipe2 (t->sleep_pipe, O_CLOEXEC); + if (err != 0) + abort (); + } + + * (pid_t *) ret = pid; + return NULL; +} + SCM_DEFINE (scm_fork, "primitive-fork", 0, 0, 0, (), "Creates a new \"child\" process by duplicating the current \"parent\" process.\n" @@ -1244,7 +1269,9 @@ SCM_DEFINE (scm_fork, "primitive-fork", 0, 0, 0, " further behavior unspecified. See \"Processes\" in the\n" " manual, for more information.\n"), scm_current_warning_port ()); - pid = fork (); + + scm_without_guile (do_fork, &pid); + if (pid == -1) SCM_SYSERROR; return scm_from_int (pid); |