Hi, On Sun 26 Feb 2012 23:00, l...@gnu.org (Ludovic Courtès) writes:
>> A guile built without >> threads may fork to its heart's content. However a guile built with >> threads -- the default, recommended configuration -- should not call >> primitive-fork. > > That’s a strong statement. Don't shoot the messenger ;) I tried hard to make it work, but there's no getting around POSIX here. > When the only threads are the main thread > and the signal thread, everything’s alright. For example, this works > fine on GNU/Linux: > > (let ((p (primitive-fork))) > (case p > ((0) > (sigaction SIGINT (lambda args > (format #t "kid ~a got ~a~%" (getpid) args) > (exit 0))) > (let loop () (loop)) > (exit 1)) > (else > (sleep 2) > (kill p SIGINT) > (format #t "killed ~a~%" p) > (waitpid p)))) > > It works because the signal thread is stuck in a read(2) with no lock > taken. "Works" ;-) It mostly works on GNU/Linux. But not all the time! Other processes can send your thread signals -- indeed, one would expect that it's for that reason that you installed a signal handler. If the signal-handling thread wakes up and queues an async, it could be in the middle of allocation, hold the alloc lock, and thereby prevent the child from allocating anything. Or it could have the async mutex. I really doubt that we can build a stable system on top of such shaky guarantees. I > Things that don’t work include this: > > (use-modules (ice-9 futures)) > > (let* ((f (future (begin (sleep 4) (getpid)))) > (p (primitive-fork))) > (case p > ((0) > (format #t "kid -> ~a~%" (touch f))) > (else > (format #t "parent -> ~a~%" (touch f)) > (waitpid p)))) > > Here the child waits forever because it has only one thread. Or because some other thread has the allocation lock, or some other lock, including even the gconv lock deep in libc, etc. > As for popen, that’s a bug (or undocumented limitation) of (ice-9 > futures) itself, more than anything else. Popen now works with threads. Andy -- http://wingolog.org/