~ chicken-core (chicken-5) 0f4a0a3d1f2f3a98fb5c9e03255345f8b1d7aace


commit 0f4a0a3d1f2f3a98fb5c9e03255345f8b1d7aace
Author:     Peter Bex <peter.bex@xs4all.nl>
AuthorDate: Wed Oct 3 22:22:55 2012 +0200
Commit:     felix <felix@call-with-current-continuation.org>
CommitDate: Thu Oct 4 23:37:57 2012 +0200

    Fix handling of EINTR in process-wait by retrying. Add combined test for this and the getc() EINTR handling bug
    
    Signed-off-by: felix <felix@call-with-current-continuation.org>

diff --git a/NEWS b/NEWS
index efe430e4..226d2447 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,8 @@
+4.8.1
+
+- Core libraries
+  - Fixed EINTR handling in process-wait and when reading from file ports.
+
 4.8.0
 
 - Security fixes
diff --git a/posixunix.scm b/posixunix.scm
index c851319f..77d8bca4 100644
--- a/posixunix.scm
+++ b/posixunix.scm
@@ -1808,14 +1808,17 @@ EOF
 
 (define (##sys#process-wait pid nohang)
   (let* ([res (##core#inline "C_waitpid" pid (if nohang _wnohang 0))]
-         [norm (##core#inline "C_WIFEXITED" _wait-status)] )
-    (values
-      res
-      norm
-      (cond [norm (##core#inline "C_WEXITSTATUS" _wait-status)]
-            [(##core#inline "C_WIFSIGNALED" _wait-status)
-              (##core#inline "C_WTERMSIG" _wait-status)]
-            [else (##core#inline "C_WSTOPSIG" _wait-status)] ) ) ) )
+	 [norm (##core#inline "C_WIFEXITED" _wait-status)] )
+    (if (and (fx= res -1) (fx= _errno _eintr))
+	(##sys#dispatch-interrupt
+         (lambda () (##sys#process-wait pid nohang)))
+	(values
+	 res
+	 norm
+	 (cond [norm (##core#inline "C_WEXITSTATUS" _wait-status)]
+	       [(##core#inline "C_WIFSIGNALED" _wait-status)
+		(##core#inline "C_WTERMSIG" _wait-status)]
+	       [else (##core#inline "C_WSTOPSIG" _wait-status)] ) )) ) )
 
 (define parent-process-id (foreign-lambda int "C_getppid"))
 
diff --git a/tests/port-tests.scm b/tests/port-tests.scm
index 72d6861f..81db14c4 100644
--- a/tests/port-tests.scm
+++ b/tests/port-tests.scm
@@ -139,6 +139,27 @@ EOF
      (check (tcp-port-numbers in))
      (check (tcp-abandon-port in)))	; Not sure about abandon-port
 
+   
+   ;; This tests for two bugs which occurred on NetBSD and possibly
+   ;; other platforms, possibly due to multiprocessing:
+   ;; read-line with EINTR would loop endlessly and process-wait would
+   ;; signal a condition when interrupted rather than retrying.
+   (set-signal-handler! signal/chld void) ; Should be a noop but triggers EINTR
+   (receive (in out)
+     (create-pipe)
+     (receive (pid ok? status)
+       (process-wait
+        (process-fork
+         (lambda ()
+           (file-close in)              ; close receiving end
+           (with-output-to-port (open-output-file* out)
+             (lambda ()
+               (display "hello, world\n")
+               ;; exit prevents buffers from being discarded by implicit _exit
+               (exit 0))))))
+       (file-close out)                 ; close sending end
+       (assert (equal? '(#t 0 ("hello, world"))
+                       (list ok? status (read-lines (open-input-file* in)))))))
    )
   (else))
 
Trap