in reply to forked die() in eval block has counterintuitive behavior?

Interesting problem and I think you just helped finding the bug I was trying to catch for the past 3 days.....
I think putting an eval block within the child code and the exit-ing instead of die-ing will solve the problem.
At least in the example you gave:
#!/usr/bin/perl -w use strict; my $num = '123'; # an external database ID, for example warn "(PID $$) Beginning transaction #$num "; eval { my $pid = fork(); if ($pid) { warn "\t(PID $$) the parent does OK"; } else { eval { warn "\t(PID $$) the child fails"; die "\t(PID $$) Child process failure"; }; warn $@ if $@; exit; } }; if ($@) { warn "(PID $$) Rolling back transaction #$num: died in eval with $ +@"; } else { warn "(PID $$) Committing transaction #$num"; }

Replies are listed 'Best First'.
Re^2: forked die() in eval block has counterintuitive behavior?
by rlucas (Scribe) on May 24, 2005 at 12:55 UTC
    Yes -- when you attack the problem, you may want to examine my patch to Mail::Mailer, which patch fixes the problem by doing two things:
    1. Eval the child code (which ideally performs and exec and hands off the baton to sendmail/whatever); if the child code dies, warn the error and exit(1);
    2. So that someone using Mail::Mailer has a way of knowing it went wrong, check the return value from closing the filehandle that had been opened on the child process; die here (in the parent!) if a problem.
    But heavens to Betsy! this is a pernicious problem. I had originally suspected that fork() was being called, so I overrode CORE::GLOBAL::fork with a debugging message and stack trace -- all to no avail, since it was the open("|-") style of forking that was being used in Mail::Mailer.