I think open-pipe leaves an extra copy of its input or output fd in the forked child. For instance, using showfds.c below and (use-modules (ice-9 popen)) (let ((p (open-input-pipe "./showfds"))) (sleep 1) (close-pipe p)) (let ((p (open-output-pipe "./showfds"))) (sleep 1) (close-pipe p)) I take it the intention is to leave the child clean except for the normal 0, 1 and 2. * popen.scm (open-process): Close input-fdes, output-fdes and error-fdes after duping them to 0, 1 and 2. I think this is worth putting in the 1.6 branch too. The only likely ill effect I could spot from the current code was that for an output pipe the extra copy of the read side means that if the spawned program closes stdin, a write from the parent (ie. guile) won't produce a SIGPIPE. For instance the following contrivance currently gets a SIGPIPE only when the sleep finishes and the shell exits, whereas with the change above it happens immediately. (use-modules (ice-9 popen)) (let ((p (open-output-pipe "exec 0>/dev/null; sleep 10"))) (while #t (display "x" p)))