3
$ perl5.8 -w -e 'if (my $pid=open(my $P, "|-")) {
      kill("SIGKILL",$pid); sleep(2); print $P "test1:$pid\n";}; '
Broken pipe

Now I'm trying to catch that broken pipe

$ perl5.8 -w -e '$SIG{PIPE} = sub {print "SIGPIPE\n";return 1}; 
   if (my $pid=open(my $P, "|-")) {
      kill("SIGKILL",$pid); sleep(2); print $P "test1:$pid\n"}; 
$

Nothing at all is printed when I would have expected SIGPIPE. It seems as if it treats my anonymous sub handler as if it was IGNORE instead.

  • Pretty much any content of the sub does not produce any effect (print, die, change package variable value)

  • The code doesn't die; if you print something to STDOUT in the end it will print.

What am I missing?


UPDATE : @jm666's answer led me to the issue: the pipe's writes were not flushed; and as such it was too early to get the SIGPIPE. Adding autoflush helped:

$ perl5.8 -w -e 'use IO::Handle ;$SIG{PIPE} = sub {print "SIGPIPE\n"}; 
   if (my $pid=open(my $P, "|-")) {
   $P->autoflush(1);
   kill(SIGTERM,$pid); sleep(2);;print $P "test1:$pid\n"}; '

SIGPIPE
$
DVK
  • 126,886
  • 32
  • 213
  • 327
  • FWIW, no problem catching the pipe with Perl 5.16. I mean the sub gets executed correctly. What's the OS by the way? – i-blis Mar 28 '14 at 23:01
  • @i-blis - I tried it on Perl 5.8 on Solaris and 5.8 and 5.12 on Linux. Unless it's some special setting in my environment, it should rule out OS specific issues; not sure if there's version-specific pipe bug between 5.12 and 5.16 – DVK Mar 28 '14 at 23:03
  • What platform are you running on? – Borodin Mar 28 '14 at 23:19
  • @Borodin - Linux dmesg is `Linux version 2.6.18-164.9.1.el5PAE (mockbuild@ls20-bc2-13.build.redhat.com) (gcc version 4.1.2 20080704 (Red Hat 4.1.2-46)) #1 SMP Wed Dec 9 03:46:34 EST 2009`. As noted I tried both 5.8 and 5.12 Perls – DVK Mar 28 '14 at 23:22
  • @Borodin - I also tried running as a script (as opposed to one-liner); and as both bash and tsch one liners in case my shell had some weirdo environment – DVK Mar 28 '14 at 23:24
  • This fails for me on Linux (CentOS 5.10) with Perl 5.8.8, but works for Perl 5.14.1, 5.16.3 or 5.18.0. Similarly on Mac OSX, 5.12.4 fails but 5.16.3 works as you would hope. – JRFerguson Mar 28 '14 at 23:29
  • @DVK: Just to be clear, your problem is resolved? You have accepted `jm66`'s answer but you say in your update that it *helped*. – Borodin Mar 29 '14 at 00:09
  • @Borodin - the main part was realizing that it was caused by non-flushing of pipe's IO... his solution was different from mine but addressed the same root cause (his answer was 95% what I needed) – DVK Mar 29 '14 at 00:10

1 Answers1

3

Physical writes to pipes are delayed, so you can catch them on the close. the next prints the message. (added the close $P)

perl -w -e '$SIG{PIPE} = sub {print "SIGPIPE\n";return 1}; if (my $pid=open(my $P, "|-")) { kill("SIGKILL",$pid); sleep(2); print $P "test1:$pid\n";close $P};'

more: http://perldoc.perl.org/perlipc.html

clt60
  • 62,119
  • 17
  • 107
  • 194
  • And the default buffering mode of pipes is just the sort of thing that might have changed between perl versions... –  Mar 28 '14 at 23:29
  • @WumpusQ.Wumbley - plausible. I'm too dead to go chase the documentation now but wouldn't be surprised – DVK Mar 28 '14 at 23:31