Re^5: Error: Not enough space
by demerphq (Chancellor) on Jan 05, 2005 at 00:32 UTC
|
You can't do a bunch of things and then check $! and have it be meaningful at all. Until you know exactly which statement caused $! to be set there is no point in looking at it at all. DBI, or any one of the modules you have in use may be setting $! inadverdantly and its value by the time you check it is actually meaningless. Put a or die "Error:$!"; everywhere it makes sense and see what happens, but drop the catchall test on $! at the end of your code, its worse than useless.
| [reply] [d/l] |
Re^4: Error: Not enough space
by Joost (Canon) on Jan 05, 2005 at 00:32 UTC
|
its very clear that some part of my code is throwing "Not enough space" error message.
Strictly speaking, you can't be sure, since errno is only defined to have a meaning immediately after an error. Not sometime later, or before an error occured.
You might be right that your program does indeed cause an ENOMEM error, but since you don't check $! at the right place, you're never going to be sure if and why it does.
You can fix this easily - system calls have a return code. Use it.
| [reply] [d/l] |
|
|
Ok in that case, which ones are considered to be system calls? is it only the system(..) calls or it is any call to underlying c routines also? Like can a call to print FH "foo"; cause ENOMEM? or can an array allocation cause an ENOMEM? so which all statements in the code should be checked for $! ?
Here's an example:
@arr = ('x', 'y', 'z');
# error occurs so $! is set. But thinking that this small piece of cod
+e wont cause any error I dont check for $! here.
#some more code her
print join(',', @arr);
open(FILE, "<file.txt") || die (".....error");
# check for $! here
if ($!)
{
# whcih is the culprit line causing this error? is it array allocation
+, or is it print or is it open?
}
| [reply] [d/l] [select] |
|
|
Ok in that case, which ones are considered to be system calls?
Good question, I thought there was a full list in the perldocs, but I can't find it - most of it is documented in perlfunc, but print() also sets $! on error (and returns false), which isn't documented there, so there might be omissions.
In general, errors from child processes in system() and `` are set in $? (though they set $! if the exec() fails), eval() errors are set in $@ and system errors that are not handled otherwise in the interpreter (not promoted to exceptions or worked around) set their errors in $! - these include file and pipe errors from print(), open(), read(), close() etc. All these functions return some value to indicate success/failure, and you should only read $! on failure.
If you want to be sure, "Programming Perl 3rd edition" (the Camel book) has a list of all built-in functions and and also notes which ones set $!.
Also, you might want to take a look at the standard (since perl 5.6) Fatal module. With it you can force an exception on functions that return false on error if you don't explicitly test for them (sadly, it doesn't work with system() and other functions that return true on error):
from the docs:
use Fatal qw/:void open close/;
# properly checked, so no exception raised on error
if(open(FH, "< /bogotic") {
warn "bogo file, dude: $!";
}
# not checked, so error raises an exception
close FH;
update: just to answer your other question: running out of memory in the interpreter will throw an exception which is untrappable by default (so your code should die on the line causing the exception). In theory, it's possible to catch this exception, but your code probably isn't trying to. See the $^M entry in perlvar.
| [reply] [d/l] [select] |
|
|
No, system calls are NOT calls to system. Calls to system don't set $!, they set $?. System calls are function calls that interact with the system, and typically have an obvious 1-1 mapping to your systems library calls that set errno. That's C/Unix speak, but to fully understand Perl, you must understand C and Unix, as large parts of Perl are designed to work with Unix.
Functions that set $! will always return a false value on failure, and a true value on success. Never, ever use $! to determine whether something succeeded or not - the specification of your system libraries allows a function to set errno to whatever it wants in case of success (all that $! does is give you the value of errno - whose value usually isn't under Perls control). Always use the return value of the function used to determine success, and only use $! immediately after determining failure. Typically this is done by interpolating $! in the message you give with die. In your example, both print and open can set $!. But if your code reaches the test for if ($!), the open has succeeded (because you'll die if it fails). Which means that at that moment, the value of $! is utterly meaningless. No information can be derived from it.
The manual page will tell you whether a function sets $!. Functions that set $! include (but aren't limited to): open, close, print, umask, chmod, unlink, rename, mkdir, rmdir, sysopen, sysread, syswrite, and fork.
| [reply] |
Re^5: Error: Not enough space
by ikegami (Patriarch) on Jan 05, 2005 at 00:36 UTC
|
Or is it that the value of $! can be "Not enough space" even without my program causing a memory exception?
Yes. Check to see if the print right before the # here I check $! returned true or false. If it returned false, that print got an error ("Not enough space."). If it returned true, $! is meaningless. Which is to say an error may or may not have occured earlier, but you have no way of knowing. This is stated in the documentation for $! in perlvar.
| [reply] [d/l] [select] |
|
|
Ok in that case, which ones are considered to be system calls? is it only the system(..) calls or it is any call to underlying c routines also? Like can a call to print FH "foo"; cause ENOMEM? or can an array allocation cause an ENOMEM? so which all statements in the code should be checked for $! ?
Here's an example:
@arr = ('x', 'y', 'z');
# error occurs so $! is set. But thinking that this small piece of cod
+e wont cause any error I dont check for $! here.
#some more code her
print join(',', @arr);
open(FILE, "<file.txt") || die (".....error");
# check for $! here
if ($!)
{
# whcih is the culprit line causing this error? is it array allocation
+, or is it print or is it open?
}
| [reply] [d/l] [select] |