mlawren has asked for the wisdom of the Perl Monks concerning the following question:

I am seeing an issue with perl v5.20.2 exiting unexpectedly, and I don't know how to track down the source of the problem. Here's the code I'm trying to run:

use strict; use warnings; use Sys::Cmd 'spawn'; my $proc = spawn( 'file-not-found' } ); $proc->stdin->print("x\n"); $proc->wait_child;

Note that Sys::Cmd (my own module) fiddles around a lot with file descriptors (and that is most likely the actual issue). But the problem I have at the moment is that the perl process appears to be terminating on the print statement:

main::(j:5): my $proc = spawn( sub { print "hello\n" } ); DB<1> n main::(j:6): warn ref $proc->stdin; DB<1> n IO::Handle at j line 6. at j line 6. main::(j:7): $proc->stdin->print("x\n"); DB<1> n mark@mlt:~/src/sys-cmd$

If I change the print statement to print {$proc->stdin} "text\n" the it appears as if perl tries to run the statement twice!

main::(j:5): my $proc = spawn( sub { print "hello\n" } ); DB<1> n main::(j:6): warn ref $proc->stdin; DB<1> n IO::Handle at j line 6. at j line 6. main::(j:7): print {$proc->stdin} "x\n"; DB<1> n main::(j:7): print {$proc->stdin} "x\n"; DB<1> n mark@mlt:~/src/sys-cmd$

Without an error message I don't even know how to debug my actual issue. Any ideas?

p.s. I'm actually running a patched version of Sys::Cmd locally so you won't be able to re-create this without modification.

Update: I've created a new branch on github that you can check out to see what I'm trying to do:

$ git clone -b unexpected-termination git://github.com/mlawren/sys-cm +d $ cd sys-cmd $ ./unexpected-termination.pl Spawning process

Update 2: I just checked and no END block is run, and the exit value after termination is 141, which means nothing to me.

Update 3: The above errors were seen on Debian GNU/Linux. I *don't* see this behaviour with Perl 5.18.3 on Win32, where the test script runs to completion with normal error reporting.

Replies are listed 'Best First'.
Re: Unexpected termination on "print" (pipe)
by tye (Sage) on Aug 14, 2015 at 14:28 UTC
    the exit value after termination is 141, which means nothing to me.

    Then perhaps you should read about $? ?

    If I change the print statement to print {$proc->st­din} "text\n" the it appears as if perl tries to run the statement twice!

    No, it is just that in print {$proc->stdin} "text\n" there are two statements in that one line. The braces actually constitute a block and so $proc->stdin is a full statement, not just an expression. So the debugger stops for that statement first and then stops for the print statement after that.

    But back to your primary question. The reason printing to a pipe usually causes a process to exit is because all readers of that pipe have now closed their handle (usually because they have exit()ed) and so the writing process gets sent SIGPIPE. This behavior should be mentioned briefly in "man 2 write" and should be covered more extensively by "man 7 pipe".

    And your exit value confirms that this is the cause in your specific case.

    - tye        

      Thanks for your reply tye. Much appreciated, especially given how deep these nodes get pushed with all the questions coming through.

      I know in principle what $? is used for, but I could not find (nor does the documentation you point to) a list matching perl exit codes (or are they system error codes?) with reasons. Should I be looking at something like errno.h?

      However your pointer to SIGPIPE was spot on. Installing a handler allowed me to deal with the error and continue execution.

      Thanks again.

        Should I be looking at something like errno.h?

        No, you should be reading the documentation that I already linked to: $?.

        - tye        

Re: Unexpected termination on "print"
by Anonymous Monk on Aug 14, 2015 at 09:40 UTC
    I'm actually running a patched version of Sys::Cmd locally so you won't be able to re-create this without modification.

    Then how are we supposed to help? Maybe you could create a branch in your GitHub repo for the module and put the code there?