signal() anomaly

S

Stephen Sprunk

My code has a certain pointer that sometimes unexpectedly becomes null.
It would be a lot of work to find every place the pointer gets
dereferenced and add a null check. So I want to just ignore it by
catching the signal.

Sorry, but the correct solution is to check for null before you
dereference a pointer, even if it is theoretically "impossible" for that
pointer to be null.

Ignoring a null pointer dereference is pretty much impossible, since
there are no sensible semantics for continuing execution after that
point--and trying to do so will probably just cause other "impossible"
bugs to appear and waste even more of your time.

Treat the disease, not the symptom.

S
 
I

Ike Naar

Sorry, but the correct solution is to check for null before you
dereference a pointer, even if it is theoretically "impossible" for that
pointer to be null.

Following this advice would make it impossible to dereference a pointer:

/* assuming pointer is non-volatile */

if (pointer != NULL)
{
/* at this point it's theoretically impossible for pointer
to be null, but let's check anyway */
if (pointer != NULL)
{
/* at this point it's theoretically impossible for pointer
to be null, but let's check anyway */
if (pointer != NULL)
{
/* at this point it's theoretically impossible for pointer
to be null, but let's check anyway */
if (pointer != NULL)
{
/* at this point it's theoretically impossible for pointer
to be null, but let's check anyway */
if (pointer != NULL)
{
/* at this point it's theoretically impossible for pointer
to be null, but let's check anyway */
if (pointer != NULL)
{
/* at this point it's theoretically impossible for pointer
to be null, but let's check anyway */

/* ... etc ad infinitum ... */

do_something_with(*pointer);

/* ... */
}
}
}
}
}
}
 
P

Paul

Johann said:
It is quite possible. In Linux, at least, where the machine state is
passed to the signal handler. You can find out the instruction that
caused the exception and advance the instruction pointer to point to the
next one, thus avoiding subsequent segfaults. This is rather difficult
with the usual variable-length opcodes, and would require limited
instruction decoding.
...
Of course, that does not mean that your program will do anything
meaningful. Register contents will end up undefined etc...

I could have mentioned as well, that debuggers are good at noting
such things, and can also alert you when one happens. You can even
single-step your new program, and watch the value of the variable
in question. The debuggers on various platforms, vary in how
"friendly" they are, and some of them, I can't run at all.
Can't seem to succeed in getting them to do anything. The last
one I ran, was in Visual Studio, and that seemed OK. Almost worthwhile,
compared to sprinkling printfs all over the place.

Paul
 
N

Nobody

I think Eric was right on the money asking about the return value. If the
signal() call returns success, but the "ignore" is ignored, I say that's a
bug in the C library. I think I'll file a bug report against glibc.

It's not a bug in glibc. You tell it to ignore SIGSEGV, it ignores
SIGSEGV. According to POSIX, ignoring a synchronous[1] SIGSEGV results in
undefined behaviour, which could mean anything, including raising SIGSEGV.

[1] One generated by an invalid memory access. A SIGSEGV generated by
kill(), sigqueue() or raise() *can* be ignored, hence it would be a bug if
glibc reported an error for signal(SIGSEGV, SIG_IGN).

Note that it *is* an error (§2.4.3) to set the action for SIGKILL or
SIGSTOP to SIG_IGN:

The system shall not allow the action for the signals SIGKILL or SIGSTOP
to be set to SIG_IGN.
 
K

Kleuske

What up

I've used signal to set SIGSEGV to SIG_IGN. But when I later dereference
a null pointer my program still crashes out with segfault SIGSEGV. What
gives?

RTFM (man signal). You cannot ignore SIGSEGV.
 
T

Tim Rentsch

Nobody said:
POSIX-2008 S2.4.3 says:

SIG_IGN

Ignore signal.

Delivery of the signal shall have no effect on the process. The behavior
of a process is undefined after it ignores a SIGFPE, SIGILL, SIGSEGV, or
SIGBUS signal that was not generated by kill(), sigqueue(), or raise().

http://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html

And also:

The behavior of a process is undefined after it returns normally from a
signal-catching function for a SIGBUS, SIGFPE, SIGILL, or SIGSEGV signal
that was not generated by kill(), sigqueue(), or raise().

Not being a POSIX expert, I wouldn't want to disagree, but I did
find this:

http://pubs.opengroup.org/onlinepubs/9699919799/functions/signal.html

The functionality described on this reference page is
aligned with the ISO C standard. Any conflict between the
requirements described here and the ISO C standard is
unintentional. This volume of POSIX.1-2008 defers to the
ISO C standard.

Not offering any conclusions, just FYAI.
 
Ö

Öö Tiib

My code has a certain pointer that sometimes unexpectedly becomes null.

The defects in software are unexpected only for inexperienced.
They are perfectly normal.
It would be a lot of work to find every place the pointer gets
dereferenced and add a null check.

Tracking the defects down and fixing them takes 60% or more of
overall development effort in any software project worth mentioning.
So I want to just ignore it by catching the signal.

This is an attempt of building a wheelchair for your invalid
program. If you could not write its abilities correctly then the
replacement abilities from wheelchair by you will be even worse.
Who needs software with disabilities in broken wheelchair?
Better repair your program, it is cheaper.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,078
Messages
2,570,570
Members
47,204
Latest member
MalorieSte

Latest Threads

Top