in reply to bad die behaviour?

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.

Replies are listed 'Best First'.
Re^2: bad die behaviour?
by Anonymous Monk on Sep 10, 2007 at 12:04 UTC
    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 $!.
        I also don't know why it returns 0. I have tried to force
        $! = 1;
        just before the die and the script ends with return code 0 to the shell.
        The functions Log and CloseLog are very simple. They write a formatted log line and close the log file.

        thanks
        Xavi
      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.