|
Author |
Message |
Peter Camero #1 / 3
|
 Using eval and $@
I'm forwarding this on behalf of a colleague: Hello, I need help using the perl 'eval' function which doesn't seem to work on my Unix system. I am trying to trap an exception using open2 on a process which is not available. $Rbin = "Run a process which has no licence"; eval { open2(\*README , \*WRITEME, $Rbin); };
Quote: } else {
print WRITEME "\n"; print WRITEME "\n"; while (<README>) { etc... Running this with the perl de{*filter*}, it crashes when I print to WRITEME. I've tried enclosing
I need to trap the error submitting the process. It could be no licence, too many users, no disk space, whatever. Can anyone help? Ceri
|
Sat, 15 May 2004 17:06:28 GMT |
|
 |
nob.. #2 / 3
|
 Using eval and $@
Quote:
> I need help using the perl 'eval' function which doesn't seem to work on my > Unix system.
The Perl eval function traps errors if the form of thown execptions that would otherwise cause Perl to terminate. Most Perl functions (inbuilt or in popular modules) that deal with the outside world do not indicate failure by throwing exceptions, they return success codes as their return values. For details see the documentation of those functions. Quote: > I am trying to trap an exception using open2 on a process which is not > available.
When performing operations that involve creating an aynchronous subprocess the subprocess the function that creates the subprocess cannot report in any way that the subprocess subsequently terminates abnormally because this would require information to travel backwards in time. This has nothing to do with Perl. This is fundamental physics. Quote: > $Rbin = "Run a process which has no licence"; > eval { open2(\*README , \*WRITEME, $Rbin); };
> } else { > print WRITEME "\n"; > print WRITEME "\n"; > while (<README>) { > etc... > Running this with the perl de{*filter*}, it crashes when I print to WRITEME. > I've tried enclosing
Ahh... this is probably a SIGPIPE problem. For historical reasons in POSIX writing to a pipe the other end of which has been closed can be treated as much more serious than normal IO errors. It actually does throw an exception ("syncronous signal") at the operating system level which terminates the running process with extreem prejudice. This operating system level exception is not trapped by eval. Trapping of signals is achieved using the %SIG special variable. I suggest that in Perl you say: $SIG{PIPE} = 'IGNORE'; This will make EPIPE behave like an ordinary IO error. (i.e. the Perl the print() to WRITEME will complete without throwing any kind of exception return but false and $! will contain the numeric and string forms of EPIPE). -- \\ ( ) . _\\__[oo
. l___\\ # ll l\\ ###LL LL\\
|
Sat, 15 May 2004 19:01:24 GMT |
|
 |
Benjamin Goldber #3 / 3
|
 Using eval and $@
Quote:
> I'm forwarding this on behalf of a colleague: > Hello, > I need help using the perl 'eval' function which doesn't seem to work > on my Unix system. > I am trying to trap an exception using open2 on a process which is not > available. > $Rbin = "Run a process which has no licence"; > eval { open2(\*README , \*WRITEME, $Rbin); };
open2 will only throw an error if pipe() or fork() fails.
if there is a liscence. Quote: > } else { > print WRITEME "\n"; > print WRITEME "\n"; > while (<README>) { > etc... > Running this with the perl de{*filter*}, it crashes when I print to > WRITEME.
This most likely means that you are writing to a pipe whose far end has been closed -- the $Rbin process has either closed it's STDIN, or else it has exited or died [which has a similar effect]. Quote:
> still not set.
That is because writing to a pipe whose far end is closed doesn't raise an exception via die(), but it raises an exception via a signal. Signals are very different animals than perl exceptions. Quote: > I need to trap the error submitting the process. It could be no > licence, too many users, no disk space, whatever.
Assuming that your error when printing to WRITEME is due to the subprocess exiting, you can find out why it exited by looking at $? after you have done a waitpid() on the number returned by open2. Of course, you have to get to that point first [ie, you have to not get killed via SIGPIPE when writing]. my $rbin = "some program"; my $pid = open2(my($readme, $writeme), $rbin); TRAP_PIPE: { local $SIG{PIPE} = sub { last TRAP_PIPE }; print $writeme "\n\n"; close $writeme or die "close failed: $!"; Quote: }
while( <$readme> ) { etc. Quote: }
close $readme or die "close failed: $!"; if( waitpid( $pid, 0 ) ) { my ($sig, $ret) = ($?&255, $?>>8); die "'$rbin' died from signal $sig" if $sig; die "'$rbin' exited with code $ret" if $ret; print "'$rbin' succeeded.\n"; Quote: } else {
die "waitpid failed: $!"; Quote: }
To learn what various exit codes indicate, you have to read the program's documentation. To learn what various signals mean, type: kill -l From your unix shell prompt. This will let learn the signal names of each signal number. I'm not going to explain what those names mean, but I will say that if that program [your $rbin thingy] dies from a signal, rather than from exiting, then something probably went wrong with it, and you should probably contact its maintainer. -- Klein bottle for rent - inquire within.
|
Fri, 21 May 2004 02:03:20 GMT |
|
|
|