in reply to wait versus close on a pipe

The close fails because of the wait done already ($! for the failure is "No child processes"). Calling wait doesn't close the pipe, however, so you can still read from it. Perl isn't maintaining the output of the program anywhere; that's the OS's job.

The OS does keep a buffer for the job's output between it and perl. If the child process fills that buffer before you read anything out of it, the child will stop (at the OS's request), and your wait loop will loop forever.

A better way to handle your pipes is with (four argument) select or IO::Select. Using select and IO::Select might be a good place to look. What you want to do is read from them when there's something to read, but don't get stuck waiting on them when there's nothing to read.

Replies are listed 'Best First'.
Re^2: wait versus close on a pipe
by pc88mxer (Vicar) on Jun 03, 2008 at 03:55 UTC
    Part of the problem is that when you create the pipe using open(..., "-|"), calling close will always try to wait for the child to exit. Most of the time closing one end of the pipe (especially the reading end), will cause the child to terminate. However, if your child is uncooperative (for instance, ignores SIGPIPE), the close call can effectively hang. If you only have one child this is generally not a problem. However, in your case you have two child processes.

    One alternative is to create the pipe using IPC::Open[23]. This will allow you to separate the closing of the pipe from the waiting/reaping of the child.

    One final comment... I would close the pipes first and then reap the children. In your situation, read whatever data you need from the child , close that child's pipe and then proceed to wait for it to terminate. This also holds if you are sending data to a child via a pipe. In that case, closing your end of the pipe sends EOF to the child which is a conventional way to tell it to finish its processing and exit.

      create the pipe using IPC::Open[­23]. This will allow you to separate the closing of the pipe from the waiting/reaping of the child.

      Note that you can close a Perl-opened pipe w/o waiting for the child by re-opening the pipe instead of directly closing it. Re-open the file handle to File::Spec->devnull() and then close that.

      - tye        

      A few things:

      • Since close does a wait, there's no reason to close the pipe and try to reap the child (unless you were referring to IPC::Open3 there).
      • If you close before the child terminates, the child will get a SIGPIPE only if it tries to write to the closed pipe (I think). It could ignore that, but it also might not ever trigger it, if it was done writing anyway.
      • A close would send EOF to the child only if the child were reading. Since the child is writing, I don't think I'd call that EOF. Rather, it's SIGPIPE.
      • I'm writing all this without testing it, and I'm starting to wonder if I should try some of these things before I talk further.