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

I'm writing something to process files in various directories. I'd like to die() if something goes wrong in any particular directory, but continue trying to process the others. But I find that eval does not do what I expect.
use File::Find; my @dirlist = ('dir1', 'dir2', 'dir3'); foreach my $dir (@dirlist){ eval { find( \&wanted, $dir }; }; # Does NOT work when passing a r +eference to foo to the find module # eval { bar() }; }; # DOES work when just calling a subroutine dir +ectly if( $@ ){ print "$dir had error: ".$@; } else { print "processed $dir\n"; } } sub wanted{ die "haha!"; } sub bar{ die "haha!"; }
Why doesn't eval{} trap the call to die() in the first case? Is that what the
$SIG{'__DIE__'}
stuff is in the eval docs? If so, would someone please explain to me what I have to do to trap the die() call in wanted()?

Replies are listed 'Best First'.
Re: Why doesn't' eval{} trap die() when using File::Find?
by ikegami (Patriarch) on Aug 03, 2010 at 19:55 UTC
    After fixing the compile errors, eval properly catches the exceptions.
    use File::Find; my @dirlist = ('.', '.', 'nonexistant'); foreach my $dir (@dirlist){ eval { find( \&wanted, $dir ) }; # Does NOT work when passing +a reference to foo to the find module # eval { bar() }; # DOES work when just calling a subroutine dir +ectly if( $@ ){ print "$dir had error: ".$@; } else { print "processed $dir\n"; } } sub wanted{ die "haha!"; } sub bar{ die "haha!"; }
    . had error: haha! at a.pl line 18. . had error: haha! at a.pl line 18. processed nonexistant

    In what way does it not work for you? Could it be that your version of F::F actually catches the exceptions?

      It works now, of course.
      Was it a PEBKAC error?.
      Thank you for your help.
Re: Why doesn't' eval{} trap die() when using File::Find?
by kennethk (Abbot) on Aug 03, 2010 at 20:02 UTC
    First, there are some typos in your code. Specifically, on line 6 you've swapped a } for a ) and you have an extra } on your commented line 8. It is generally considered good form to test code before you post (How do I post a question effectively?).

    Fixing those, I do not have any trouble trapping the die when I modify your directory list to correspond to an actual directory in my tree. If the directory does not exist, your wanted sub never executes. Are you sure that perl is executing at the path you think it is? Also note that if you have warnings enabled, your eval will not catch File::Find's emitted warnings.

    use File::Find; my @dirlist = qw(.); foreach my $dir (@dirlist){ eval { find( \&wanted, $dir ); }; # Does NOT work when passing a r +eference to foo to the find module # eval { bar() ; }; # DOES work when just calling a subroutine dire +ctly if( $@ ){ print "$dir had error: ".$@; } else { print "processed $dir\n"; } } sub wanted{ die "haha!"; } sub bar{ die "haha!"; }
Re: Why doesn't' eval{} trap die() when using File::Find?
by Anonymous Monk on Aug 03, 2010 at 19:59 UTC
    If I add
    use strict; use warnings;
    the error is obvious
    $ perl junk852728.pl syntax error at junk852728.pl line 9, near "$dir }" Global symbol "$dir" requires explicit package name at junk852728.pl l +ine 14. Global symbol "$dir" requires explicit package name at junk852728.pl l +ine 16. Unmatched right curly bracket at junk852728.pl line 18, at end of line syntax error at junk852728.pl line 18, near "}" Execution of junk852728.pl aborted due to compilation errors.
    } is not the same as )
    -eval { find( \&wanted, $dir }; }; +eval { find( \&wanted, $dir ); };