rovf has asked for the wisdom of the Perl Monks concerning the following question:
I found this in Perl 5.8.8 and 5.10, but not in 5.8.7:
It's not a real problem, but I wonder why $! is set here. I had a look at strict.pm, but didn't find anything which might possibly set $! in this case.> perl -lwe "use strict; print qq($!)" Bad file descriptor > perl -lwe "print qq($!)" >
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re: "use strict" sets $!
by ig (Vicar) on Aug 19, 2009 at 11:35 UTC | |
I had a look at strict.pm, but didn't find anything which might possibly set $! in this case. strict.pm is a file. When use strict; is compiled perl searches the directories in @INC until it finds the strict.pm file. Several system calls may be executed as it traverses @INC. Even if strict.pm is in the first directory in @INC, at least two system calls will be required to open the file and read its contents. These system calls could set errno as they succeed. strict.pm sets several variables. Doing so may cause perl to acquire more memory from the system. The system call (perhaps malloc) may set errno when it succeeds. So there are at least a few system calls involved in loading the strict module, any one of which might have set errno, causing $! to be set. | [reply] [d/l] |
by rovf (Priest) on Aug 19, 2009 at 12:26 UTC | |
Several system calls may be executed as it traverses @INC. Good point. This explains why I didn't find anything conspicuous inside strict.pm itself. Thanks for the explanation!
-- Ronald Fischer <ynnor@mm.st> | [reply] [d/l] |
by JavaFan (Canon) on Aug 19, 2009 at 13:47 UTC | |
| [reply] [d/l] [select] |
by ig (Vicar) on Aug 19, 2009 at 22:18 UTC | |
True enough. I was only pointing out that there were system calls and didn't mean to suggest that any of those I mentioned were responsible for setting errno in this case or that it was an exhaustive list. Investigating a little further, I find that several different versions of perl on my system (CentOS 5.3) produce the same result. Looking more closely at 5.10.1-RC1, it appears errno is being set to EBADF in PerlIO_fast_gets, with the following stack trace at the time:
The function is:
So, system calls I note in passing that there are at least about 115 (give or take a few cpp conditionals and macros) places in the perl source where errno is set and about 54 places where errno is set to EBADF. While I have found one place where errno is set to EBADF it is possibly not the last place where this value is set before the perl reads the value according to the print statement. Additional study would be required to confirm that this is the cause of $! being set when printed in the OP program. | [reply] [d/l] [select] |
|
Re: "use strict" sets $!
by ig (Vicar) on Aug 19, 2009 at 10:12 UTC | |
IIRC $! is only in a defined state after a failed system call, though there might be a few places where perl or some module sets it to zero before a system call. If the last system call didn't fail, $! is not guaranteed to be zero - it may have any value and its value is without defined meaning. man 3 errno on my CentOS system says: The <errno.h> header file defines the integer variable errno, which is set by system calls and some library functions in the event of an error to indicate what went wrong. Its value is significant only when the call returned an error (usually -1), and a function that does succeed is allowed to change errno. Thus one of the possibilities you should consider is that the last system call succeeded but left errno with a non-zero value. Another possibility is that the last system call (or the last N system calls) all succeeded without changing the value of errno and it still has the value set from either the immediately preceding failed system call (which should have set it) or some subsequent successful system call. In other words, it might be quite difficult to determine which system call set it. | [reply] [d/l] |
by rovf (Priest) on Aug 19, 2009 at 11:06 UTC | |
If the last system call didn't fail, $! is not guaranteed to be zeroI know that! That's why I wondered what in "use strict" might have caused a failed system call. I didn't find anything in the code of strict.pm which might have caused errno to be set. Just out of curiosity...
-- Ronald Fischer <ynnor@mm.st> | [reply] [d/l] [select] |
by ig (Vicar) on Aug 19, 2009 at 11:21 UTC | |
I wondered what in "use strict" might have caused a failed system call Maybe you know this also but your quest for a failed system call suggests that maybe you don't or that there might be some confusion... The fact that $! is non-zero is not an indication that any system call failed. If you know that the last system call failed then the value of $! has meaning, otherwise its value doesn't mean anything at all. | [reply] |
by rovf (Priest) on Aug 19, 2009 at 12:22 UTC | |
by ig (Vicar) on Aug 19, 2009 at 13:08 UTC | |
|
Re: "use strict" sets $!
by cdarke (Prior) on Aug 19, 2009 at 11:33 UTC | |
For example, the perl interpreter could try to load a .pm file (like strict.pm) from different locations in @INC. It might not find it in the first directory it searches. A failure would set errno but a success would not reset it. I don't know for a fact if that is the exact cause of this particular error but my own guess. That would explain why not using strict does not set $! - no modules have been searched for. Update: The difference in releases could just mean that the @INC is different and it finds the module in the first directory searched. | [reply] |
|
Re: "use strict" sets $!
by Anonymous Monk on Aug 19, 2009 at 09:21 UTC | |
| [reply] |
by rovf (Priest) on Aug 19, 2009 at 09:29 UTC | |
I'm sitting here on a Windoze platform, so I first need to look for some free strace. Maybe I'll try StraceNT...
-- Ronald Fischer <ynnor@mm.st> | [reply] [d/l] |
by Anonymous Monk on Aug 19, 2009 at 09:58 UTC | |
| [reply] |
by superfrink (Curate) on Aug 19, 2009 at 22:30 UTC | |
I ran grep ' E' on each output file to check for system calls that returned an error. (This may not find all errors.) Here is the diff. The lines starting with < are in the strace from running with use strict;. Maybe the difference is related to the language settings or the ioctl on file descriptor 4. The strace output shows: Update: I'm running perl 5.10.0 on Ubuntu 9.04. | [reply] [d/l] [select] |