On Wed, Jul 23, 2014 at 4:00 AM, Christian Millour <cm.perl@abtela.com> wrote: > > I can't think of a compelling reason for require to reset $! (and corrupt > $^E) when successful, instead of restoring their values on entry. And indeed > it seems to me that dSAVE_ERRNO, SAVE_ERRNO and RESTORE_ERRNO exist in > perl.h to deal with exactly such situations (and furthermore DTRT wrt. $^E). > An analysis together with a tentative patch have been proposed here : > https://rt.perl.org/Public/Bug/Display.html?id=116118#txn-1181050 , and no > objection were raised. > > Could this tentative patch please be updated as needed and applied/smoked ? > I can formalize a patch if needed but would rather have the original author > (Craig) get the credit. > > Thanks for your time and consideration. The problem is my patch doesn't actually do what you want. It does successfully restore any errno that is set in pp_require while rifling through @INC trying to find the file being required (assuming the file is eventually found and successfully opened). But after it's opened, the file is sent to S_doeval to be compiled, and somewhere in there errno gets cleared again. I haven't figured out exactly how or where yet. There is a call to CLEAR_ERRSV(), which has been there in some form since Perl 5.000. That might be what's clearing errno, or not; I don't know. It doesn't look like it would, but maybe there's magic on PL_errgv or something. On the surface, it sounds reasonable that a successful require should leave errno in the state it was in prior to the require. But nothing resembling a complete or well-though-out implementation has been proposed, and any change in this area will involve touching sensitive bits of the core that have been as they are for twenty years. A reformulated patch is attached, but at best it's a partial solution. For future reference, here's what you get with my patch: $ type foo.t @INC = qw(Perl Rules ../lib); $e = $! = 13; $se = $^E = 13; print '# $! is ' . (0+$!) . ' $^E is ' . (0+$^E) . "\n"; # Should look in 'Perl', then 'Rules' (unsuccessfully), then '../lib' require 'version.pm'; print '# $! is ' . (0+$!) . ' $^E is ' . (0+$^E) . "\n"; $ perl foo.t # $! is 13 $^E is 13 # $! is 0 $^E is 0 So you can see that errno is still cleared in require even though I restore it after finding version.pm.Thread Previous | Thread Next