2

After upgrading to Perl 5.24.4 we repeatedly get this error in logs (without pointing the filename and line number):

Unable to flush stdout: Broken pipe

We have no idea what causes this error.

Is there any advice how to understand the cause of the error?

melpomene
  • 84,125
  • 8
  • 85
  • 148
porton
  • 5,214
  • 11
  • 47
  • 95
  • what is your `shebang` top of your script? – Gerhard May 24 '18 at 11:14
  • @GerhardBarnard We have hundreds, maybe thousands of scripts. The main problem is that it's unknown which script causes the error. Shebangs are `#!/usr/bin/perl` or `#!/usr/local/bin/perl`. Symlink `/usr/bin/perl -> /usr/local/bin/perl` – porton May 24 '18 at 11:25
  • 1
    and your new perl version is at this location? If it is, then I will delete my comments, just trying to figure possible reasons. – Gerhard May 24 '18 at 11:29
  • 1
    How did you upgrade perl? – Borodin May 24 '18 at 11:45
  • @GerhardBarnard The new perl is at the same location as before. – porton May 24 '18 at 12:24
  • @Borodin I suppose our system admin installed a new version of FreeBSD perl package – porton May 24 '18 at 12:25
  • Verify the name of the file as being `perl` and not something like `perl5..` – Gerhard May 24 '18 at 12:28
  • @porton: You can't just install a new perl on top of the old one; it sounds like you need to delete everything and reinstall from scratch. But if the sysop did the upgrade then it's their job to fix it. – Borodin May 24 '18 at 12:29

3 Answers3

5

The error comes from perl.c, line 595:

        PerlIO_printf(PerlIO_stderr(), "Unable to flush stdout: %s",
                      Strerror(errno));

This line is part of perl_destruct, which is called to shut down the perl interpreter at the end of the program.

As part of the global shutdown procedure, all still open filehandles are flushed (i.e. all buffered output is written out). The comment above says:

 /* Need to flush since END blocks can produce output */
 /* flush stdout separately, since we can identify it */

The error message is not listed in perldoc perldiag, which is arguably a documentation bug. It was probably overlooked because it's not a real warn or die call, it's effectively just print STDERR $message. It's not associated with a file name or line number because it only happens after your program stops running (i.e. after a call to exit or because execution fell off the end of the main script).

melpomene
  • 84,125
  • 8
  • 85
  • 148
2

This is very general advice, but

use Carp::Always;

at the top of the script, or running with

perl -MCarp::Always the_script.pl arg1 arg2 ...

will get Perl to produce stack traces with every warning and error.

mob
  • 117,087
  • 18
  • 149
  • 283
  • 1
    Great advice, but it won't help in this case. [This is neither a warning nor an exception.](https://stackoverflow.com/a/52106594/589924) – ikegami Sep 02 '18 at 18:46
  • You can avoid overriding the shebang line by using `PERL5OPT=-MCarp::Always the_script.pl arg1 arg2 ...` – ikegami Sep 02 '18 at 18:47
2

Broken pipe is the error string associated with system error EPIPE. One receives this error when writing to a closed pipe. Writing to a closed pipe usally results in the process being killed by a SIGPIPE, so it means the behaviour of SIGPIPE was changed from its default.

$ perl -e'
   $SIG{PIPE} = "IGNORE";
   print "foo\n"
      or die("Can\x27t write to STDOUT: $!\n");
   sleep(2);
   close(STDOUT)
      or die("Unable to flush STDOUT: $!\n");
' | perl -e'sleep(1)'
Unable to flush STDOUT: Broken pipe

As melpomene discovered, the error is automatically output if you write to a broken pipe in an END block.

$ perl -e'
   $SIG{PIPE} = "IGNORE";
   sleep(2);
   END { print "foo\n"; }
' | perl -e'sleep(1)'
Unable to flush stdout: Broken pipe

This isn't necessarily a problem, although it could be a sign that a process is exiting prematurely.

ikegami
  • 367,544
  • 15
  • 269
  • 518
  • It can be simplified: `perl -e '$SIG{PIPE} = "IGNORE"; sleep(1); print "foo\n";' | echo -n` is a short code which produces this error – porton Sep 08 '18 at 14:15