Beefy Boxes and Bandwidth Generously Provided by pair Networks
go ahead... be a heretic
 
PerlMonks  

bad die behaviour?

by Anonymous Monk
on Sep 10, 2007 at 11:13 UTC ( [id://638035]=perlquestion: print w/replies, xml ) Need Help??

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

I write scripts that need to report exit status to the applications that call them. I found that when I call die from inside a subroutine, the return code is always 0. Even playing with $! doesn't have any effect. die called outside any subroutine has the right behaviour and ends the program with a non 0 return code (or can be forced by using the $! variable). Tested on Unix and Windows and ActiveState Perl 5.8.8. You can check this with: perl -e 'die'; echo $? perl -e 'sub {die}': echo $? Is this a bug or I'm doing something wrong?

Replies are listed 'Best First'.
Re: bad die behaviour?
by johngg (Canon) on Sep 10, 2007 at 11:24 UTC
    Doing

    $ perl -e 'sub {die}'

    is just setting up an anonymous subroutine in void context then exiting with a normal termination status because it never actually dies. Note the following

    $ perl -e '$sub = sub {die}; $sub->();' Died at -e line 1. $ echo $? 255 $

    Cheers,

    JohnGG

    Update: To test behaviour in a script rather than on the command line.

    use strict; use warnings; sub toDieFor { my $v = shift; die qq{Died with $v}; } my $value = shift; toDieFor($value) if $value > 10; print qq{Normal termination\n};

    Running this a couple of times

    $ spw638035 3 Normal termination $ spw638035 33 Died with 33 at spw638035 line 9. $ echo $? 255 $

    Perhaps you could shows us an actual code sample that triggers the behaviour you describe.

Re: bad die behaviour?
by bruceb3 (Pilgrim) on Sep 10, 2007 at 11:34 UTC
    Let's see;
    $ perldoc -f die

    die LIST

    Outside an "eval", prints the value of LIST to "STDERR" and exits with the current value of $! (errno). If $! is 0, exits with the value of "($? >> 8)" (backtick `command` status). If "($? >> 8)" is 0, exits with 255. ... snip ...

    Let's see how this works.

    $ perl -e '$! = 10; die "blah\n"' blah $ echo $? 10

    Seems to work as described in the doco.

      I have chosen a bad example trying to simplify the problem, as I have not realised that defining a sub is not executing it. In real world I have a module with utility subs and one of them is FatalError $msg as:
      sub FatalError { my $message = shift; my ($package, $filename, $line) = caller; Log "ERROR","$message ($filename linea $line)"; CloseLog; die "ERROR: $message ($filename linea $line)\n"; }
      then I use it in a script as in:
      $conn = Net::SFTP::Foreign::Compat->new($ftp_host,(user => $ftp_user)) +; if ( $conn->error ) { my $errormsg=$!; FatalError "Error: $errormsg"; }
      Result is the error message appears in the log but the script finishes with 0 return code.
      I have tried to force the return code with $! but with no positive result.


      Thanks
      Xavi

        I don't know why you're getting zero — you should never get zero from die — but your code is broken since Log and CloseLog probably change $!.
        Why do think that the Net::SFTP::Foreign::Compat will set $! if there is a problem? Looking at the source code for that module, the only time that $! is used is when there is a problem opening or communicating to a local file or pipe. Also, the doco for Net::SFTP::Foreign::Compat says that it will call die if there is a 'low-level protocol error or unexpected error message' so you would need to wrap your use of the module up in a eval block to catch the exception.

        On to the FatalError sub.

        bruce:1:~/tmp $ cat p.pl #!/usr/bin/perl use strict; use warnings; sub Log { } sub CloseLog { } sub FatalError { my ($message, $exit_status) = @_; my ($package, $filename, $line) = caller; Log "ERROR", "$message ($filename linea $line)"; CloseLog; $! = $exit_status; die "ERROR: $message ($filename linea $line)\n"; } FatalError "testing", 34; # <- 34 should be the value of $? bruce:1:~/tmp $ ./p.pl ERROR: testing (./p.pl linea 19) bruce:1:~/tmp $ echo $? 34 bruce:1:~/tmp $

        Try rearranging your code. Good luck.

        Cheers.

Re: bad die behaviour?
by cdarke (Prior) on Sep 10, 2007 at 12:49 UTC
    Just tried your code on Windows ActiveState 5.8.8. with the calls to Log and CloseLog commented out: the script returns 255 correctly.
      I tried the same on HP/UX and it doesn't work for me: the script returns 0, even forcing $!=1 before the die.

      thanks
      Xavi
Re: bad die behaviour?
by ikegami (Patriarch) on Sep 10, 2007 at 14:04 UTC
    Are you really doing script : echo $?? I'm not familiar with the details of unix shell scripting, but maybe $? gets interpolated too soon. Try breaking it down into two commands.
      All the trouble and confusion was caused by bugs in the Net::SFTP::Foreign module.
      I've upgraded to the latest version and now it works. I don't fully understand why it failed yet, but seems that some die inside the module could be the cause.
      Thank you all
      Xavi

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://638035]
Approved by Corion
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others pondering the Monastery: (2)
As of 2024-04-25 02:09 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found