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

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

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

    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).

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

      I feel this phrasing is slightly misleading...

      ZOMBIE is the final state of a process (It does not "run" anymore). In that state all ressources used by the process are freed, all except one, the slot corresponding to the process in the kernel process table. If the father of that process is not a daemon and finishes eventually (even without handling /SIGC(H)?LD/) then the process is orphaned and init will reclaim it . If the father is a daemon then it *must* handle /SIGC(H)?LD/ or there is potential for the system process table to fill up. After that chaos is guaranteed, as nobody can fork!

      Some systems allow a process to ignore /SIGC(H)?ILD/ so that the system does the reaping for it. I think it's POSIX but not (yet) fully portable. Note Un*x does not do this reaping systematically as the information is useful especially if you just want to control a pool of processes etc...The single UNIX spec (since 98 I think -- at least my HP-UX 11.0 manpage says so) does sanctify the "ignore" shortcut.

      cheers --stephan

      "can_write" is actually short for "can write without blocking". If trying to write will immediately fail, then it won't block, which is what select cares about (and so makes "can write" true). Just like if reading will immediately fail because of end-of-stream or because of an error, then "can read" becomes true because trying to read won't block ("hang").

      - tye        

        Actually the only guarantee for writing is 1 byte (supposing you don't get an error) so if you try to write more you might block, that's why if you don't want to be blocked you need to go all the way to non-blocking handles (which is never easy as you have to deal with partial writes).

        If I need to go non-blocking I usually use a variation on Lincoln's Stein IO::SessionData and IO::SessionSet. Sadly they are packaged with SOAP::Lite, and having "godzilla" as a prerequesite is no fun ;) IO::Multiplex is also interesting.

        hth --stephan