|
From: Charles W. <cwi...@us...> - 2011-03-30 18:01:09
|
On 3/30/2011 12:05 PM, LRN wrote:
> probably happens somewhere at the bottom of
> the binary stack (i've checked the script part up to the point where it
> calls close() builtin, the builtin appears to return 0, wrongly of
> course), close to the interpreter (either that, or the errno-evaluating
> part is hidden too well for me to find it), which might mean that the
> problem lies in some *other* piece of code that gets executed by the
> interpreter *after* the call to perl_something_IO_whatever_close(), but
> *before* script-level builtin close() returns.
I think, but am not sure, it's the magic bit of code that makes errno
available to the perl interpreter via $! (it's "magic" because it also
supports modifiers like '$!{ENOENT}' [true iff errno=ENOENT], and
evaluations in a string context automatically call perl's equivalent of
strerror).
However, AFAICT the code that handles $! is decoupled from the return
value processing -- so it doesn't have any knowledge of the fact that,
"well, hey, this system call returned success so I should actually
ignore/reset errno in THIS case, but not others..."
OTOH, agreeing with our consensus on the meaning -- or rather, the lack
thereof -- of errno after success, perl is unambiguous about it:
======================================================================
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:
if (open my $fh, "<", $filename) {
# Here $! is meaningless.
...
} else {
# ONLY here is $! meaningful.
...
# Already here $! might be meaningless.
}
# Since here we might have either success or failure,
# here $! is meaningless.
In the above meaningless stands for anything: zero, non-zero, undef. A
successful system or library call does not set the variable to zero.
If used as a string, yields the corresponding system error string. 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. (Mnemonic: What just went bang?)
======================================================================
and it is certainly possible that the problematic bits we are seeing are
simply violating that restriction. But I don't think that's the case
(otherwise, it'd be common to see the "failure" on other platforms, not
just MSYS with its 'strict posix but very surprising' behavior).
Also, one of the consequences of MSys's behavior is that immediately
after a failure (as viewed by a perl client), I get the *wrong* errno.
E.g. if system('app-no-exist.exe') fails because exec() is unable to
locate app-no-exist, I SHOULD see EACCESS, EINVAL, ENOENT, or ENOEXEC.
But instead, I see EBADF (now, granted, perhaps THIS is a simple bug in
perl's system() implementation, where it ought to save errno after a
failed exec, before close()ing the various redirection fd's, and then
restore it ...)
But...it's one thing to say "well, great, msys's strict standards
conformance is exposing real bugs that should be fixed in the client"
and quite another to say "and there are 1000 of them, and I can spend
months tracking them all down and fixing or hiding them individually" --
or we can make MSYS conform to the de facto behavior of all other unix
platforms with a one line change, and I can move on to something more
fun. Like doing my taxes. :-P
But yeah, I've failed to really discover the 'easily fixable' Real
Bug(tm) -- if it is, in fact, 'easily fixable'. And, I don't have any
more time to hunt.
--
Chuck
|