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

You shouldn't use print with select. Had you used sysrwite, I bet it would have returned "successfully wrote 0 bytes" (defined and == 0). In other words, the child had ended. (Well, technically, the child has closed its STDIN, but it did that when it ended.)

Try

my $msg = "msg\n"; foreach my $w (IO::Select->new($wh)->can_write()) { my $rv = syswrite($w, $msg, length($msg)); if (not defined $rv) { die("Unable to send data to child\n"); } if (not $rv) { warn("Child is no longer accepting input\n"); $w_sel->remove($w); next; } if ($rv != length($msg)) { warn("Pipe is full. We'd normally call select again\n"); next; } print "Successfully sent message to the child\n"; }

Don't forget to reap your children with waitpid.

Replies are listed 'Best First'.
Re^2: Pipes and IO::Select's method can_write()
by almut (Canon) on Feb 02, 2007 at 18:43 UTC

    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)

      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