Index
Home
About
Blog
From: torek@elf.bsdi.com (Chris Torek)
Newsgroups: comp.lang.c
Subject: Re: scanf() weirdness, take 2
Date: 9 Feb 1997 14:56:04 -0800
In article <5divp1$mea@elf.bsdi.com> I wrote (rather briefly) that:
>>... errno is allowed to be set, and apparently to ERANGE, even on
>>non-errors [from strtol]
In article <y87mkhkfzu.fsf@qcd.lanl.gov> Tanmoy Bhattacharya
<tanmoy@qcd.lanl.gov> wrote:
>Can you give a reference?
Well, no need anymore; you already did. :-)
>I found in 7.1.3 ...
(and 7.10.1.5 (ISO numbering), wording that implies that strtol()
itself will not change errno arbitrarily, but is only allowed to set
it to ERANGE on error).
>The only relevant problem that I see is in 6.1.2.4, where it is not
>even clear that errno continues to refer to the same object throughout
>the life of the program. ...
This was the `really ugly' situation I was thinking of.
>I usually discard such ugly possibilities in c.l.c because it is
>likely that the standard was just loosely worded and, in all
>likelihood, this was not an intended reading of that section.
I agree that this is at least beyond the intent of the Standard
(which is why I said `a sufficiently perverse implementation'),
and would not normally bring it up here. There is, however, another
situation in which errno gets set, usually *not* to ERANGE, `during'
a call to strtol(), in real programs that are not strictly conformant
ANSI/ISO C programs. In particular, programs that catch signals
and do more than simply set a flag may end up setting errno at
`unpredictable' times. Consider the (not strictly conforming) code
fragment:
void catch(int sig) {
if (interrupted == 0) {
interrupted = 1;
} else if (double_interrupt == 0) {
fprintf(stderr, "\n[interrupt -- one more to kill]\n");
double_interrupt = 1;
} else {
/* interrupted twice; jump to top level */
longjmp(toplevel, INTERRUPTED);
}
}
This kind of code might sit inside an interpreter. A single user
`abort' sets a flag (of type sig_atomic_t) that the interpreter
checks `often'. For stubborn cases (perhaps the interpreter calls
compiled code that may fail to check the interrupt flag), you can
bang on abort three times and get a longjmp() back to the command
loop, possibly leaving the internals a bit messed up, but at least
back to where you can inspect the system's state.
Now, at the two-interrupt point, this particular code prints to
stderr, and many actual implementations have a side effect of
setting errno to ENOTTY on some (the `first for the stream') calls
to fprintf(). The overall effect in this case can be (and, in
practise, has been) to cause errno to get `mysteriously' set,
apparently `during' the operation of a function like strtol().
Again, this is not strictly conforming code, but because this kind
of `false errno' does occur in practise, I find the suspenders-and-
belt approach (of checking errno only if the function's return value
suggests an error) to be safer.
(If you *are* building a non-conformant system that does `real work'
in a signal handler, you can try saving and restoring errno. In
general, this works fairly well, and prevents this kind of problem.
It might be nice if the C runtime environment for Unix-like systems
saved errno in the signal trampoline code, so that you did not have
to; that too would prevent this kind of error.)
--
In-Real-Life: Chris Torek, Berkeley Software Design Inc
El Cerrito, CA Domain: torek@bsdi.com +1 510 234 3167
Antispam notice: unsolicited commercial email will be handled at
my consulting rate of $200/hr.
Index
Home
About
Blog