in reply to Re: Pipes and IO::Select's method can_write()
in thread Pipes and IO::Select's method can_write()

Thanks ikegami.   Seems plausible... (and I first went "you could've known, Almut, you were already using sysread for reading..." to myself).

But when I actually tried it, even with the code you suggested, I'm still getting a SIGPIPE (which, when uncaught, causes the script to be killed). More precisely, what I get now is

BROKEN PIPE Unable to send data to child

(BTW, this is Perl 5.8.8 on Linux - in case it matters)

Replies are listed 'Best First'.
Re^3: Pipes and IO::Select's method can_write()
by ikegami (Patriarch) on Feb 02, 2007 at 18:56 UTC

    You have two mechanisms to detect the child ending. You can either ignore SIGPIPE signals and wait for syswrite to return 0, or you can listen for SIGPIPE signals. It's your choice. (Well, I suppose you could do both.)

    As for print vs syswrite, the problem with print is that it will block until all the data is sent. If that's not desireable, the data needs be appended to a buf and sent when can_write says you can. At that point, syswrite will only send as much as it can without blocking. (Remove the chars that were sent from the buffer, and wait on can_write again).

    If you do use print, make sure the file handle is flushed or auto-flushed.

      You can either ignore SIGPIPE signals and wait for syswrite to return 0, or you can listen for SIGPIPE signals

      I think you meant "return undef" here...

      Call me a Un*x biggot but I have been thinking about this some more. I just could not quite remember something about SIGPIPE and sockets in the context of a select loop.

      First let us look at the easy case i.e pipes or fifos. By default they are "blocking".

    • A SIGPIPE is an exceptional condition (like the receiving of any other signal except SIGCHILD maybe as it is a system "rule"): a write to a pipe or fifo without reader will generate a SIGPIPE for that writer.
    • EOF on a fifo or pipe is a normal condition, generated when the last writer on a FIFO closes it (in the case of a pipe when the writer closes it) and the reader tries to read.
    • In the context of a select loop EOF at the read end of a connection is also a normal condition. Two system calls actually cooperate: select indicates a desc.(fh) is ready for reading if the next read gives EOF; in that case Perl's sysread will return num. 0.

      Select will indicate that a desc.(fh) is ready for writing when the other end has closed its side of the connection. The next call to syswrite will return undef (and sets $! to EPIPE) and in complete analogy with the pipe/fifo case a SIGPIPE will be generated.

      Still there is an important difference, in a select loop you usually manage quite a few "write" desc. and an isolated signal does not really pinpoint the "guilty" desc.; so usually you would mostly ignore SIGPIPE in the context of a select loop (not so for a "pipeline"). This is what I could not remember at first.

      hth --stephan

      You're right that, in this particular case, STDIN is closed as a consequence of the child having terminated. OTOH, you get exactly the same behaviour, if the child is still alive, but doesn't take input (as when explicitly having closed STDIN)1. And the reason why the message can't be written wasn't what I was primarily interested in.

      I was mainly just wondering why the can_write() method does essentially say "Yes, I can write", if it can't... I.e. why it can't figure out that there is some problem on the other end (or, at least, doesn't tell you).   Somehow, I'd think that it would require more detailed status info to tell that the process on the other end is actually listening and ready to receive another chunk of data, than it would require to simply detect that all communication has been shut down...

      However, I'm confident that - if that's just how things are - I'll be able to accept the fact and live with it, even if it strikes me as a little inconsequent ;)

      Anyhow, thanks for taking the time to reply.

      ___

      1  To verify, I used a little script in place of /bin/echo :

      #!/usr/bin/perl my $s = shift; close STDIN; print $s x 1000000; # write enough to fill up output buffer # sleep 10; # or, just sleep

        I was mainly just wondering why the can_write() method does essentially say "Yes, I can write", if it can't...

        The underlying function is called select. can_write is a misnomer. It doesn't alert of the ability to write. It alerts the receipt of a write event. The inability to write is a write event.

        you get exactly the same behaviour, if the child is still alive, but doesn't take input (as when explicitly having closed STDIN)

        In both cases, the child explicitly closed STDIN. In both cases, the child is not (completely) dead. It only disappears after waitpid allows it to die.

        why it can't figure out that there is some problem on the other end (or, at least, doesn't tell you)

        But that's exactly what it does! select tells you there's an event, and syswrite tells you what the event is. It's convenient how you are saved from making a third system call.

        Something else that might be of interest is knowing when a child becomes a zombie. I don't know if unix allows you to be alerted of such an event, but it can be determined by polling waitpid($pid, WNOHANG).