~ 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