~ chicken-core (chicken-5) 47b5be71353305425a419831ff2a5682a5c39df1


commit 47b5be71353305425a419831ff2a5682a5c39df1
Author:     felix <felix@call-with-current-continuation.org>
AuthorDate: Sun Oct 28 12:37:22 2012 +0100
Commit:     Peter Bex <peter.bex@xs4all.nl>
CommitDate: Mon Oct 29 21:26:41 2012 +0100

    Added optional argument to process-fork that allows killing all threads in the child process but the current one
    
    Signed-off-by: Peter Bex <peter.bex@xs4all.nl>

diff --git a/library.scm b/library.scm
index 680687fb..ffd01914 100644
--- a/library.scm
+++ b/library.scm
@@ -4382,7 +4382,9 @@ EOF
    '()					; #12 recipients
    #f) )				; #13 unblocked by timeout?
 
-(define ##sys#primordial-thread (##sys#make-thread #f 'running 'primordial ##sys#default-thread-quantum))
+(define ##sys#primordial-thread
+  (##sys#make-thread #f 'running 'primordial ##sys#default-thread-quantum))
+
 (define ##sys#current-thread ##sys#primordial-thread)
 
 (define (##sys#make-mutex id owner)
@@ -4404,6 +4406,9 @@ EOF
        (##sys#setslot ct 1 (lambda () (return (##core#undefined))))
        (##sys#schedule) ) ) ) )
 
+(define (##sys#kill-other-threads thunk)
+  (thunk))	     ; does nothing, will be modified by scheduler.scm
+
 
 ;;; Interrupt-handling:
 
diff --git a/manual/Unit posix b/manual/Unit posix
index 66325a6a..170c644a 100644
--- a/manual/Unit posix	
+++ b/manual/Unit posix	
@@ -649,12 +649,15 @@ of the {{PATH}} environment variable while {{execve(3)}} does not.
 
 ==== process-fork
 
-<procedure>(process-fork [THUNK])</procedure>
+<procedure>(process-fork [THUNK [KILLOTHERS?]])</procedure>
 
 Creates a new child process with the UNIX system call
 {{fork()}}. Returns either the PID of the child process or 0. If
 {{THUNK}} is given, then the child process calls it as a procedure
-with no arguments and terminates.
+with no arguments and terminates. If {{THUNK}} is given and the
+optional argument {{KILLOTHERS?}} is true, then kill all other
+existing threads in the child process, leaving only the current thread
+to run {{THUNK}} and terminate.
 
 ==== process-run
 
diff --git a/posixunix.scm b/posixunix.scm
index 0277cc59..90fedd5c 100644
--- a/posixunix.scm
+++ b/posixunix.scm
@@ -1767,14 +1767,19 @@ EOF
 ;;; Process handling:
 
 (define process-fork
-  (let ([fork (foreign-lambda int "C_fork")])
-    (lambda thunk
-      (let ([pid (fork)])
-      (cond [(fx= -1 pid) (posix-error #:process-error 'process-fork "cannot create child process")]
-            [(and (pair? thunk) (fx= pid 0))
-             ((car thunk))
-             ((foreign-lambda void "_exit" int) 0) ]
-            [else pid] ) ) ) ) )
+  (let ((fork (foreign-lambda int "C_fork")))
+    (lambda (#!optional thunk killothers)
+      (let ((pid (fork)))
+	(when (fx= -1 pid) 
+	  (posix-error #:process-error 'process-fork "cannot create child process"))
+	(if (and thunk (zero? pid))
+	    ((if killothers
+		 ##sys#kill-other-threads
+		 (lambda (thunk) (thunk)))
+	     (lambda ()
+	       (thunk)
+	       ((foreign-lambda void "_exit" int) 0) ))
+	    pid)))))
 
 (define process-execute
   ;; NOTE: We use c-string here instead of scheme-object.
diff --git a/scheduler.scm b/scheduler.scm
index d3a2620f..7ff3d5f0 100644
--- a/scheduler.scm
+++ b/scheduler.scm
@@ -527,3 +527,30 @@ EOF
     (##sys#remove-from-timeout-list t)
     (##sys#clear-i/o-state-for-thread! t)
     (##sys#thread-basic-unblock! t) ) )
+
+
+;;; Kill all threads in fd-, io- and timeout-lists and assign one thread as the
+;   new primordial one. Overrides "##sys#kill-all-threads" in library.scm.
+
+(set! ##sys#kill-other-threads 
+  (let ((exit exit))
+    (lambda (thunk)
+      (let ((primordial ##sys#current-thread))
+	(define (suspend t)
+	  (unless (eq? t primordial)
+	    (##sys#setslot t 3 'suspended))
+	  (##sys#setslot t 11 #f)      ; block-object (may be thread)
+	  (##sys#setslot t 12 '()))    ; recipients (waiting for join)
+	(set! ##sys#primordial-thread primordial)
+	(set! ready-queue-head (list primordial))
+	(set! ready-queue-tail ready-queue-head)
+	(suspend primordial)	     ; clear block-obj. and recipients
+	(for-each
+	 (lambda (a) (suspend (cdr a)))
+	 ##sys#timeout-list)
+	(set! ##sys#timeout-list '())
+	(for-each
+	 (lambda (a) (suspend (cdr a)))
+	 ##sys#fd-list)
+	(thunk)
+	(exit)))))
diff --git a/types.db b/types.db
index 940c6e04..b7b61218 100644
--- a/types.db
+++ b/types.db
@@ -1717,7 +1717,8 @@
 (process-execute
  (#(procedure #:clean #:enforce) process-execute (string #!optional (list-of string) (list-of string)) noreturn))
 
-(process-fork (#(procedure #:enforce) process-fork (#!optional (procedure () . *)) fixnum))
+(process-fork (#(procedure #:enforce) process-fork (#!optional (procedure () . *) *) fixnum))
+
 (process-group-id (#(procedure #:clean #:enforce) process-group-id () fixnum))
 (process-run (#(procedure #:clean #:enforce) process-run (string #!optional (list-of string)) fixnum))
 (process-signal (#(procedure #:clean #:enforce) process-signal (fixnum #!optional fixnum) undefined))
Trap