diff options
| -rw-r--r-- | scsh-process.scm | 71 | 
1 files changed, 39 insertions, 32 deletions
| diff --git a/scsh-process.scm b/scsh-process.scm index 3682c68..1a6c22b 100644 --- a/scsh-process.scm +++ b/scsh-process.scm @@ -115,11 +115,13 @@              (error 'process-wait                     "Not a scsh-type process object or pid"                     pid-or-process)) -          ;; We need to make a copy because when waiting for #f, we +          ;; We need to make a copy when waiting for #f, because we            ;; can't predict which pid we'll receive, and the SIGCHLD            ;; handler will drop the pid from the pending list.            (let ((pending-before -                 (hash-table-copy *scsh-pending-processes*)) +                 (if pid-or-process +                     *scsh-pending-processes* +                     (hash-table-copy *scsh-pending-processes*)))                  (p (if (and pid-or-process (number? pid-or-process))                         (hash-table-ref/default *scsh-pending-processes*                                                 pid-or-process #f) @@ -128,36 +130,41 @@                  (values (scsh-process-exit-status p)                          (scsh-process-ok? p)                          (scsh-process-pid p)) -		(if (and p (not nohang)) -		    (let lp ((m (make-mutex))) -		      (mutex-unlock! m (scsh-process-child-condition p)) -                      (if (not (scsh-process-exit-status p)) -                          (lp m) ; might have been forcibly unblocked -                          (values (scsh-process-exit-status p) -                                  (scsh-process-ok? p) -                                  (scsh-process-pid p)))) -		    (handle-exceptions exn -                      (if (and p (scsh-process-exit-status p)) ; Signal might've occurred -			  (values (scsh-process-exit-status p) -				  (scsh-process-ok? p) -				  (scsh-process-pid p)) -			  (abort exn)) -		      (receive (pid ok? status) -                          (posix-process-wait (if p -                                                  (scsh-process-pid p) -                                                  pid-or-process) nohang) -			(cond -			 ((zero? pid) (values #f #f #f)) -			 (else -                          (and-let* ((p (or p (hash-table-ref/default -                                               pending-before pid #f)))) -                            (scsh-process-exit-status-set! p status) -                            (scsh-process-ok?-set! p ok?) -                            (condition-variable-broadcast! -                             (scsh-process-child-condition p))) - -                          (remove-scsh-pending-process! pid) -                          (values status ok? pid)))))))))) +		(handle-exceptions exn +                    (if (and p (scsh-process-exit-status p)) ; Signal might've occurred +                        (values (scsh-process-exit-status p) +                                (scsh-process-ok? p) +                                (scsh-process-pid p)) +                        (abort exn)) +                  (let lp () +                    (receive (pid ok? status) +                        (posix-process-wait +                         (if p (scsh-process-pid p) pid-or-process) +                         ;; When we have p, "nohang" is ignored because +                         ;; the thread will hang on the condition var +                         ;; rather than letting the entire process hang. +                         (if p #t nohang)) +                      (cond +                       ((zero? pid) +                        (if nohang +                            (values #f #f #f) +                            (let ((m (make-mutex))) +                              (mutex-unlock! m (scsh-process-child-condition p)) +                              (if (not (scsh-process-exit-status p)) +                                  (lp)  ; could be forcibly unblocked +                                  (values (scsh-process-exit-status p) +                                          (scsh-process-ok? p) +                                          (scsh-process-pid p)))))) +                       (else +                        (and-let* ((p (or p (hash-table-ref/default +                                             pending-before pid #f)))) +                          (scsh-process-exit-status-set! p status) +                          (scsh-process-ok?-set! p ok?) +                          (condition-variable-broadcast! +                           (scsh-process-child-condition p))) + +                        (remove-scsh-pending-process! pid) +                        (values status ok? pid))))))))))    (set-signal-handler!     signal/chld | 
