utils: 'filtered-port' doesn't leave dangling processes behind.

* guix/utils.scm (filtered-port): Make sure the 'execl' child process
  always exits, and does (primitive-_exit 1) upon execution failure.
  Use 'primitive-_exit' in the 'dump-port' child process.
* tests/utils.scm ("filtered-port, does not exist"): New test.
master
Ludovic Courtès 2014-03-22 21:50:12 +01:00
parent ca534666aa
commit 443eb4e950
2 changed files with 27 additions and 8 deletions

View File

@ -155,18 +155,29 @@ COMMAND (a list). In addition, return a list of PIDs that the caller must
wait. When INPUT is a file port, it must be unbuffered; otherwise, any wait. When INPUT is a file port, it must be unbuffered; otherwise, any
buffered data is lost." buffered data is lost."
(let loop ((input input) (let loop ((input input)
(pids '())) (pids '()))
(if (file-port? input) (if (file-port? input)
(match (pipe) (match (pipe)
((in . out) ((in . out)
(match (primitive-fork) (match (primitive-fork)
(0 (0
(close-port in) (dynamic-wind
(close-port (current-input-port)) (const #f)
(dup2 (fileno input) 0) (lambda ()
(close-port (current-output-port)) (close-port in)
(dup2 (fileno out) 1) (close-port (current-input-port))
(apply execl (car command) command)) (dup2 (fileno input) 0)
(close-port (current-output-port))
(dup2 (fileno out) 1)
(catch 'system-error
(lambda ()
(apply execl (car command) command))
(lambda args
(format (current-error-port)
"filtered-port: failed to execute '~{~a ~}': ~a~%"
command (strerror (system-error-errno args))))))
(lambda ()
(primitive-_exit 1))))
(child (child
(close-port out) (close-port out)
(values in (cons child pids)))))) (values in (cons child pids))))))
@ -184,7 +195,7 @@ buffered data is lost."
(dump-port input out)) (dump-port input out))
(lambda () (lambda ()
(false-if-exception (close out)) (false-if-exception (close out))
(primitive-exit 0)))) (primitive-_exit 0))))
(child (child
(close-port out) (close-port out)
(loop in (cons child pids))))))))) (loop in (cons child pids)))))))))

View File

@ -142,6 +142,14 @@
(append pids1 pids2))) (append pids1 pids2)))
(equal? (get-bytevector-all decompressed) data))))) (equal? (get-bytevector-all decompressed) data)))))
(test-assert "filtered-port, does not exist"
(let* ((file (search-path %load-path "guix.scm"))
(input (open-file file "r0b")))
(let-values (((port pids)
(filtered-port '("/does/not/exist") input)))
(any (compose (negate zero?) cdr waitpid)
pids))))
(false-if-exception (delete-file temp-file)) (false-if-exception (delete-file temp-file))
(test-equal "fcntl-flock wait" (test-equal "fcntl-flock wait"
42 ; the child's exit status 42 ; the child's exit status