It's a little deeper than that.
use Devel::Peek;
$! = 0.0;
Dump($!);
stat("non_existing_file");
Dump($!);
die "died at first stat" if -$!;
stat("non_existing_file");
Dump($!);
die "died at second stat" if -$!;
now yields
SV = PVMG(0x82c690) at 0x803478
REFCNT = 1
FLAGS = (GMG,SMG,pIOK,pNOK)
IV = 0
NV = 0
PV = 0
MAGIC = 0x804900
MG_VIRTUAL = &PL_vtbl_sv
MG_TYPE = PERL_MAGIC_sv(\0)
MG_OBJ = 0x803460
MG_LEN = 1
MG_PTR = 0x8032d0 "!"
SV = PVMG(0x82c690) at 0x803478
REFCNT = 1
FLAGS = (GMG,SMG,pIOK,pNOK)
IV = 0
NV = 0
PV = 0
MAGIC = 0x804900
MG_VIRTUAL = &PL_vtbl_sv
MG_TYPE = PERL_MAGIC_sv(\0)
MG_OBJ = 0x803460
MG_LEN = 1
MG_PTR = 0x8032d0 "!"
died at first stat at bug.pl line 6.
pNOK is now set, but the value hasn't been updated by stat itself. It's only when $! is referenced that the updated value materializes.
I certainly wouldn't recommend using -$!, but
perlvar
says
If used numerically, yields the current value of the C "errno" variable, or in other words, if a system or library call fails,
it sets this variable. This means that the value of $! is meaningful only immediately after a failure:
so one can be excused for doing numerical things. It also says
You can assign a number to $! to set errno if, for
instance, you want "$!" to return the string for error n, or
you want to set the exit value for the die() operator.
and having to assign a non-integer value to avoid surprises doesn't fall in my category of "do what I mean". | [reply] [d/l] [select] |
pNOK is now set, but the value hasn't been updated by stat itself. It's only when $! is referenced that the updated value materializes.
Correct. It's set by SvGETMAGIC, which is called when the value of a magic SV is needed. The state of pNOK and the like should be completely ignored by -$! since negation should call SvGETMAGIC, but negation isn't calling SvGETMAGIC in the OP's version of Perl.
| [reply] [d/l] |
| [reply] |
This was a toy example. -$! is returned from a perl callback for which it makes sense to return a negated errno back to C. Unfortunately, strange bugs started to pop up under FreeBSD, and this issue could be related to it.
Thanks everyone for helping.
| [reply] |