Using eval and $@ 
Author Message
 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  
 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  
 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  
 
 [ 3 post ] 

 Relevant Pages 

1. Test for eval() without using eval() ??

2. Using eval() for subroutine unwind

3. Using eval to iterate over a set of Perl variables

4. Using eval

5. Using Eval Statement To Trap Module Not Present Fatal Error

6. using eval to create formats

7. Using eval in regex

8. how to setup exit routine using eval

9. using eval

10. dynamic object instantiation using eval

11. problem using eval with array of file test operators

12. Bug when using eval

 

 
Powered by phpBB® Forum Software