Hi all,

nothing mission critical, just something I don't fully understand yet :)   More precisely, the can_write() method of IO::Select doesn't seem to test what I think its name would suggest.

While playing around with How and When to read STDOUT after using open3() funciton? I encountered a problem when trying to write to the filehandle that open3() connects to STDIN of the command being run. My initial code (simplified to the minimum) was as follows:

#!/usr/bin/perl use strict; use warnings; use IPC::Open3; use IO::Select; my @cmd = qw'echo bar'; # writing to 'echo' fails #my @cmd = qw'cat'; # ... while 'cat' works open3(my $wh, my $rh, undef, @cmd); # tiny delay, so the command gets enough time to close STDIN # (prevent potential race condition, in this demo script) select undef,undef,undef, 0.1; my $msg = "foo"; #----- print $wh "$msg\n"; close $wh; #----- my $data = ""; if (IO::Select->new($rh)->can_read()) { print "reading from $rh ('@cmd |')\n"; while (sysread($rh, my $buffer, 1000)) { $data .= $buffer; } } print "data: $data\n";

Problem with this code is that it simply terminates before it starts doing anything useful. Apparently, the issue is that the command being run via open3() is closing STDIN, so an attempt to write to it causes a SIGPIPE, which in turn leads to the script being killed by the default signal handler... Or some such.   Ok, silly thing to do... to write to a program that doesn't take input, but anyway.

So, I changed the section between the #----- to read:

#----- # handle SIGPIPE ourselves, so we don't get killed $SIG{PIPE} = sub { warn "BROKEN PIPE\n" }; if (my ($w) = IO::Select->new($wh)->can_write()) { if (print $w "$msg\n") { print "wrote '$msg' to $w ('| @cmd')\n"; close $w; } else { warn "print to $w FAILED\n"; # we'll have gotten a SIGPIPE, too } } else { warn "$wh not ready for writing\n"; } #-----

I would've thought that carefully testing with can_write() would avoid running into the situation that's causing the SIGPIPE... However, this doesn't seem to be the case. With the command being echo I still get

BROKEN PIPE print to GLOB(0x6ff5b0) FAILED reading from GLOB(0x6ff360) ('echo bar |') data: bar

while with cat things work as expected (as it doesn't close STDIN):

wrote 'foo' to GLOB(0x63c160) ('| cat') reading from GLOB(0x6ff5a0) ('cat |') data: foo

With echo I would have expected to see

GLOB(0x6ff5b0) not ready for writing reading from GLOB(0x6ff360) ('echo bar |') data: bar

Can someone explain why this doesn't work as I first thought it should?

Hm, on second thought, I figure it has to do with the writability referring to the local side of the pipe only, rather than the entire pipe including the status of the remote side...(?) Which brings up the question: is there a 'proper' way to test if the pipe can be written to (other than waiting for the SIGPIPE to happen, and then handling it)?   Thanks.


In reply to Pipes and IO::Select's method can_write() by almut

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.