I work on a large cgi application that consists of multiple scripts. To keep the size of each script down, we autoload a lot of general-purpose subs from separate files. I realized last week that we ignore a lot of useful information by not checking $!, so I tried to add a new sub to make checking $! convenient. I ran into a problem, though, where autoloading my sub seemed to reset $!.

I narrowed the problem down to the fact that doing the following wipes out $!:

eval {require "file"};
At first I thought that maybe $! behaves like $@, in that you could count on it being undef if whatever you just did was successful. But that wasn't true: when I replaced my eval line with an unlink of a file that did exist, $! still had the error from the first, unsuccessful unlink ($^E was reset, though).

Does anyone know why the eval{require..} sets $! even though it's successful? Here's a little program that shows what I've tried, independent of autoloading or any other complications of my larger program:

# this sets $! and $^E unlink 'asdfasdfewtwertwevbncvbnmarewrawer'; # This wipes them both out. # Note that test.pl contains only "1;", and $@ is undef afterwards. eval {require "test.pl"}; print "\$\@: $@\n" if $@; # If I comment the eval line out, this prints: # error?: last system error: No such file or directory # (error number: 2) (extended error info: The system # cannot find the file specified # Otherwise it just prints: # error? print "error?: ", &CheckLastSystemError(), "\n"; # Here's my sub. Feel free to add suggestions for it also if you have + any. sub CheckLastSystemError { my @message; # check the string value push @message, "$!" if $!; # we could check $^E here, too... # check the number value my $numericTest = 0 + $!; # force numeric context push @message, "(error number: $numericTest)" if $numericTest; # $^E is sometimes just the same as $! push @message, "(extended error info: $^E" if ($^E && $^E ne $!); if (scalar @message) { # combine @message into a string and return it return "last system error: @message"; } else { return undef; } }
This is not a big dilemma for me since I've worked around it for now by putting my sub into our main library file which always gets required. It is something I'd like to figure out if I could, though, since some of our error handling subs are also autoloaded and might potentially wipe out $! themselves.

In reply to why would a successful eval of a require reset $!? by blahblahblah

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.