diff options
author | Andy Wingo <wingo@pobox.com> | 2013-01-17 12:38:56 +0100 |
---|---|---|
committer | Andy Wingo <wingo@pobox.com> | 2013-01-17 12:38:56 +0100 |
commit | a796d0a95442b379a9ff2cdf9e0eb6efccc5dc08 (patch) | |
tree | 05142a024acdb1691f7617293cf1da92ddfd3ae3 | |
parent | 36c210d14e8572939901b9251492a3f4bf94988c (diff) | |
download | guile-a796d0a95442b379a9ff2cdf9e0eb6efccc5dc08.tar.gz |
warn on multithreaded fork
* libguile/posix.c (scm_fork): Issue a warning on a multithreaded fork.
* doc/ref/posix.texi (Processes): Add note about multithreaded fork.
* test-suite/tests/00-socket.test: Moved here, from socket.test, so as
to run before any threads are created.
* test-suite/Makefile.am: Adapt.
-rw-r--r-- | doc/ref/posix.texi | 15 | ||||
-rw-r--r-- | libguile/posix.c | 16 | ||||
-rw-r--r-- | test-suite/Makefile.am | 2 | ||||
-rw-r--r-- | test-suite/tests/00-socket.test (renamed from test-suite/tests/socket.test) | 0 |
4 files changed, 31 insertions, 2 deletions
diff --git a/doc/ref/posix.texi b/doc/ref/posix.texi index 0a688e92d..18aadca85 100644 --- a/doc/ref/posix.texi +++ b/doc/ref/posix.texi @@ -1,7 +1,7 @@ @c -*-texinfo-*- @c This is part of the GNU Guile Reference Manual. @c Copyright (C) 1996, 1997, 2000, 2001, 2002, 2003, 2004, 2006, 2007, -@c 2008, 2009, 2010, 2011, 2012 Free Software Foundation, Inc. +@c 2008, 2009, 2010, 2011, 2012, 2013 Free Software Foundation, Inc. @c See the file guile.texi for copying conditions. @node POSIX @@ -1785,6 +1785,19 @@ Creates a new ``child'' process by duplicating the current ``parent'' process. In the child the return value is 0. In the parent the return value is the integer process ID of the child. +Note that it is unsafe to fork a process that has multiple threads +running, as only the thread that calls @code{primitive-fork} will +persist in the child. Any resources that other threads held, such as +locked mutexes or open file descriptors, are lost. Indeed, @acronym{POSIX} +specifies that only async-signal-safe procedures are safe to call after +a multithreaded fork, which is a very limited set. Guile issues a +warning if it detects a fork from a multi-threaded program. + +If you are going to @code{exec} soon after forking, the procedures in +@code{(ice-9 popen)} may be useful to you, as they fork and exec within +an async-signal-safe function carefully written to ensure robust program +behavior, even in the presence of threads. @xref{Pipes}, for more. + This procedure has been renamed from @code{fork} to avoid a naming conflict with the scsh fork. @end deffn diff --git a/libguile/posix.c b/libguile/posix.c index 4d5fdcf96..324f21b78 100644 --- a/libguile/posix.c +++ b/libguile/posix.c @@ -1249,6 +1249,22 @@ SCM_DEFINE (scm_fork, "primitive-fork", 0, 0, 0, #define FUNC_NAME s_scm_fork { int pid; + if (scm_ilength (scm_all_threads ()) != 1) + /* Other threads may be holding on to resources that Guile needs -- + it is not safe to permit one thread to fork while others are + running. + + In addition, POSIX clearly specifies that if a multi-threaded + program forks, the child must only call functions that are + async-signal-safe. We can't guarantee that in general. The best + we can do is to allow forking only very early, before any call to + sigaction spawns the signal-handling thread. */ + scm_display + (scm_from_latin1_string + ("warning: call to primitive-fork while multiple threads are running;\n" + " further behavior unspecified. See \"Processes\" in the\n" + " manual, for more information.\n"), + scm_current_warning_port ()); pid = fork (); if (pid == -1) SCM_SYSERROR; diff --git a/test-suite/Makefile.am b/test-suite/Makefile.am index 880e1e2cf..9fba7b8b3 100644 --- a/test-suite/Makefile.am +++ b/test-suite/Makefile.am @@ -23,6 +23,7 @@ SUBDIRS = standalone vm SCM_TESTS = tests/00-initial-env.test \ + tests/00-socket.test \ tests/alist.test \ tests/and-let-star.test \ tests/arbiters.test \ @@ -114,7 +115,6 @@ SCM_TESTS = tests/00-initial-env.test \ tests/regexp.test \ tests/session.test \ tests/signals.test \ - tests/socket.test \ tests/srcprop.test \ tests/srfi-1.test \ tests/srfi-6.test \ diff --git a/test-suite/tests/socket.test b/test-suite/tests/00-socket.test index 6deb28542..6deb28542 100644 --- a/test-suite/tests/socket.test +++ b/test-suite/tests/00-socket.test |