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

Hello,

I have written a nice little service that is supposed run all the time as a background process handling requests from other programs, converting them to SOAP requests and dispatching them to a SOAP server via https. I am using the excellent SOAP::Lite toolkit and have hit a problem I don't really understand. When SOAP::Lite encounters a fatal problem it often calls die. Coming from the world of C and C++ I expect library functions I call to return a value or throw an exception, not to abort the entire program. This is especially true in my case as I can't have SOAP problems dropping my service. Currently I have hacked around it by dispatching my requests in forked processes and then watching for a SIG CHILD to let me know the process exited, but this is cludgy and memory intensive. Is there a way to catch the die signal and continue with the program?


Thank you,
Blake Woolbright
  • Comment on Keeping perl alive after a module calls die.

Replies are listed 'Best First'.
Re: Keeping perl alive after a module calls die.
by Fletch (Bishop) on Feb 27, 2004 at 19:29 UTC

    Read the SOAP::Lite perldoc, specifically the part about on_fault().

Re: Keeping perl alive after a module calls die.
by kvale (Monsignor) on Feb 27, 2004 at 19:27 UTC
    If you wrap your call in an eval block, you can trap that die signal and read out the error:
    eval { dangerous() } if ($@) { print "dangerous died with the error: $@\n"; }

    -Mark

Re: Keeping perl alive after a module calls die. (making die() work like warn())
by gmpassos (Priest) on Feb 27, 2004 at 21:13 UTC
    update: Take a look in the module Die::Alive. It does exactly what the code below does.

    You always can put your code inside an eval, but if you want to really make die() work like warn(), even for outside code, and keep the app running, you need to overwrite the die() function.

    Soo, here I show you an example of how to do that, and note that the BEGIN code, need to be loaded before compile any other code. Soo, this BEGIN code need to be the first thing in your script, since what is compiled before overwrite the die() function, won't keep the overwrite reference:

    sub BEGIN { *CORE::GLOBAL::die = \&DIE_2_WARN ; $SIG{__DIE__} = \&DIE_2_WARN ; } sub DIE_2_WARN { warn(@_) ;} die("This die() won't exit!") ; print "And here we continue the app...\n" ; eval { die("die inside eval!"); print "Won't go out of eval!\n" ; } ;
    As we can see, if you make die() work like warn(), a die() that is made inside an eval() won't work like generally we want, that is to go out of the eval. Soo, we need to handle that too, using the predefined variable $^S:
    sub BEGIN { *CORE::GLOBAL::die = \&DIE_2_WARN ; $SIG{__DIE__} = \&DIE_2_WARN ; } sub DIE_2_WARN { if ( $^S ) { CORE::die(@_) ;} else { warn(@_) ;} } die("This die() won't exit!") ; print "And here we continue the app...\n" ; eval { die("die inside eval!"); print "And this print won't be executed.\n" ; } ; print "ERROR: $@\n" ;
    Enjoy!

    Graciliano M. P.
    "Creativity is the expression of the liberty".

Re: Keeping perl alive after a module calls die.
by Jenda (Abbot) on Feb 27, 2004 at 21:01 UTC

    let me quote part of the documentation of die():

    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. Inside an "eval()," the error message is stuffed into $@ and the "eval" is terminated with the undefined value. This makes "die" the way to raise an exception.
    Which means that SOAP::Lite does exactly what you wanted. It throws an exception :-)

    You just have to catch it:

    eval { some code that might die() }; if ($@) { handle the exception you find in $@ }

    Jenda
    Always code as if the guy who ends up maintaining your code will be a violent psychopath who knows where you live.
       -- Rick Osborne

    Edit by castaway: Closed small tag in signature

Re: Keeping perl alive after a module calls die.
by imcsk8 (Pilgrim) on Feb 28, 2004 at 00:19 UTC
    you could check the Error.pm module, it offers a nice try/catch interface.
    ignorance, the plague is everywhere --guttermouth
Re: Keeping perl alive after a module calls die.
by Anonymous Monk on Jun 03, 2004 at 21:19 UTC
    Thanks everyone. The application works wonderfully. It has been trucking along for about 2 months now without a restart and seems to be perfectly content in its implementation.