signal handling in C

S

subramanian

Consider the following code: segment violation is deliberately
generated to catch the SIGSEGV signal. The handler for this signal,
namely SIGSEGV_handler, is called. However after the handler is
finished, control does not return to the printf statement in main()
which is present after the strcpy statement. Instead Segmentation
violation error message is printed in Redhat Linux and the program is
aborted. In VC++, the SIGSEGV_handler is called and then the program
crashes. Is this the expected behaviour ?

void SIGSEGV_handler(int num);

int main(void)
{
char *str = NULL;

signal(SIGSEGV, SIGSEGV_handler);
strcpy(str, "TEST");
printf("After signal handling\n");

return 0;
}

void SIGSEGV_handler(int num)
{
printf("SIGSEGV_handler called with the argument %d\n", num);

return;
}
 
R

Richard Heathfield

subramanian said:
Consider the following code: segment violation is deliberately
generated to catch the SIGSEGV signal. The handler for this signal,
namely SIGSEGV_handler, is called. However after the handler is
finished, control does not return to the printf statement in main()
which is present after the strcpy statement. Instead Segmentation
violation error message is printed in Redhat Linux and the program is
aborted. In VC++, the SIGSEGV_handler is called and then the program
crashes. Is this the expected behaviour ?

void SIGSEGV_handler(int num);

int main(void)
{
char *str = NULL;

signal(SIGSEGV, SIGSEGV_handler);
strcpy(str, "TEST");
printf("After signal handling\n");

return 0;
}

void SIGSEGV_handler(int num)
{
printf("SIGSEGV_handler called with the argument %d\n", num);

return;
}

foo.c: In function `main':
foo.c:5: `NULL' undeclared (first use in this function)
foo.c:5: (Each undeclared identifier is reported only once
foo.c:5: for each function it appears in.)
foo.c:7: warning: implicit declaration of function `signal'
foo.c:7: `SIGSEGV' undeclared (first use in this function)
foo.c:9: warning: implicit declaration of function `printf'
make: *** [foo.o] Error 1

If I fix those, I get the behaviour you report. This is not entirely
unexpected from a C language perspective, since the behaviour of the
program is undefined:

"If the signal occurs other than as the result of calling the abort
or raise function, the behavior is undefined if the signal handler
calls any function in the standard library other than the signal
function itself..."
 
S

subramanian

What should be done to catch signals and proceed with execution from
the next statement onwards in the program

subramanian said:


Consider the following code: segment violation is deliberately
generated to catch the SIGSEGV signal. The handler for this signal,
namely SIGSEGV_handler, is called. However after the handler is
finished, control does not return to the printf statement in main()
which is present after the strcpy statement. Instead Segmentation
violation error message is printed in Redhat Linux and the program is
aborted. In VC++, the SIGSEGV_handler is called and then the program
crashes. Is this the expected behaviour ?
void SIGSEGV_handler(int num);
int main(void)
{
char *str = NULL;
signal(SIGSEGV, SIGSEGV_handler);
strcpy(str, "TEST");
printf("After signal handling\n");
return 0;
}
void SIGSEGV_handler(int num)
{
printf("SIGSEGV_handler called with the argument %d\n", num);
return;
}foo.c: In function `main':
foo.c:5: `NULL' undeclared (first use in this function)
foo.c:5: (Each undeclared identifier is reported only once
foo.c:5: for each function it appears in.)
foo.c:7: warning: implicit declaration of function `signal'
foo.c:7: `SIGSEGV' undeclared (first use in this function)
foo.c:9: warning: implicit declaration of function `printf'
make: *** [foo.o] Error 1

If I fix those, I get the behaviour you report. This is not entirely
unexpected from a C language perspective, since the behaviour of the
program is undefined:

"If the signal occurs other than as the result of calling the abort
or raise function, the behavior is undefined if the signal handler
calls any function in the standard library other than the signal
function itself..."
 
C

Chris Torek

void SIGSEGV_handler(int num);

int main(void)
{
char *str = NULL;

signal(SIGSEGV, SIGSEGV_handler);
strcpy(str, "TEST");
printf("After signal handling\n");

return 0;
}

void SIGSEGV_handler(int num)
{
printf("SIGSEGV_handler called with the argument %d\n", num);

return;
}

This code is full of simple mechanical errors (does not compile
because, e.g., SIGSEGV is not defined at all, since you did not
"#include" the appropriate headers). If you fix those, however,
the code remains undefined by the C Standards, and full of more
important errors even on those systems where the behavior *is*
predictable.

In particular, those systems that (a) somehow catch the invalid
first value in the strcpy() call and (b) actually enter your
SIGSEGV handler in a useful way will generally either:

- reset the SIGSEGV handler to the default ("terminate program
with core dump" behavior), or
- temporarily defer additional SIGSEGVs, keeping the handler
installed and re-enabling it upon return from the handler.

They will also provide -- in a manner that cannot be obtained using
the simple Standard C handler shown above -- additional arguments
pinpointing (or perhaps just "generally getting close to", depending
on the hardware) the instruction pointer at the time the signal
occurred. To get this information you should[%] use a different
call, such as the POSIX sigaction(), to install the handler. Then,
inside the handler, you may be required to modify the provided
machine state -- which is rather naturally machine-dependent, i.e.,
will differ on an Intel vs a PowerPC vs a SPARC vs a MIPS -- if
you intend for the program to do anything useful upon returning
from the handler. If you leave the state unchanged, there is a
significant possibility that returning from the handler will take
you back to the faulting instruction, which will just immediately
fault again, calling the handler again (assuming you have set the
correct options for sigaction() or whatever the correct call may
be), and leading to an endless loop that, aside from the complexities
of signal handling, is effectively identical to:

for (;;)
;

Hence, the code you really need is OS- and machine-dependent and
cannot be written in portable C. You therefore need some other
newsgroup(s), such as comp.unix.programmer, comp.os.linux.*,
comp.os.ms-windows.*, etc., or (probably better) the documentation
for your hardware, compiler, and/or operating system.

[% It may or may not be possible to get the extra information when
using the Standard C "signal" interface, but it is probably unwise
to attempt this unless the documentation for your system specifically
says to do so. In some cases, the extra information is available
more or less "by accident", and a future version of the system may
move it elsewhere without warning.]
 
V

vijay kalkoti

Please see the man page "signal" ( manual 7, man 7 signal ).

There is an action associated with each signal handler. And it
specifies the action to be taken. When SIGSEGV is received, the action
taken is "Core" i.e, terminate the process and dump core. Apart from
calling the user defined signal handler. And that is the reason for not
printing the subsequent print() statement.

Thanks & Regards
--vijayck
 
K

Kohn Emil Dan

What should be done to catch signals and proceed with execution from
the next statement onwards in the program


A possible option can be using the longjmp() and setjmp()
functions/macros, as follows. If your implementation allows calling
printf() from within signal handlers, you can uncomment the printf()
inside the signal handler.

Emil


#include <signal.h>
#include <stdio.h>
#include <setjmp.h>

jmp_buf jbuf;

void SIGSEGV_handler(int num);

int main(void)
{
char *str = NULL;

signal(SIGSEGV, SIGSEGV_handler);
if (!setjmp(jbuf))
strcpy(str, "TEST");
printf("After signal handling\n");

return 0;
}

void SIGSEGV_handler(int num)
{
/*printf("SIGSEGV_handler called with the argument %d\n", num);*/
longjmp(jbuf,1);
}
 
L

loic-dev

Hello,
Consider the following code: segment violation is deliberately
generated to catch the SIGSEGV signal. The handler for this signal,
namely SIGSEGV_handler, is called. However after the handler is
finished, control does not return to the printf statement in main()
which is present after the strcpy statement. Instead Segmentation
violation error message is printed in Redhat Linux and the program is
aborted. In VC++, the SIGSEGV_handler is called and then the program
crashes. Is this the expected behaviour ?

The problem you are facing can't be answered within the C standard.
This is OS dependent. For instance, on UNIX/Linux, the following apply:

<quote SUSv3>
If and when the function [signal handler] returns, if the value of sig
was SIGFPE, SIGILL, or SIGSEGV or or any other implementation-defined
value corresponding to a computational exception, the behavior is
undefined.
</quote SUSv3>

That means, everything can happen... On some UNIX, the message
"SIGSEGV_handler called with the argument 11" will be repeated forever,
because the PC or the
effective address that took the SIGSEGV isn't modified, causing the
SIGSEGV to be repeated... This makes a really nice infinite loop,
actually.

HTH,
Loic.
 
C

Chris Dollin

Kohn said:
A possible option can be using the longjmp() and setjmp()
functions/macros, as follows. If your implementation allows calling
printf() from within signal handlers, you can uncomment the printf()
inside the signal handler.

Using `longjmp` inside a signal handler in Standard C gives you
undefined behaviour (unless the signal was provoked by `abort`
or `raise`).

The OP will need implementation-dependant signal handling code.
(Maybe he can rely on some other standard to make it less
implementation-dependant that it could be.)
 
K

Kohn Emil Dan

Kohn Emil Dan wrote:
Using `longjmp` inside a signal handler in Standard C gives you
undefined behaviour (unless the signal was provoked by `abort`
or `raise`).


Can you point me where the standard mentions this?
The OP will need implementation-dependant signal handling code.
(Maybe he can rely on some other standard to make it less
implementation-dependant that it could be.)


In my opinion any non-trivial C program needs some implementation
dependent features, so I agree with you.


Emil
 
R

Richard Bos

Kohn Emil Dan said:
Can you point me where the standard mentions this?

7.14.1.1#5: "If the signal occurs other than as the result of calling
the abort or raise function, the behavior is undefined if ... the signal
handler calls any function in the standard library other than the abort
function, the _Exit function, or the signal function with the first
argument equal to the signal number corresponding to the signal that
caused the invocation of the handler."
longjmp() is a function in the standard library other than those three,
so calling it in a signal handler has UB unless the signal was caused by
abort() or raise().

Richard
 

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
473,755
Messages
2,569,536
Members
45,014
Latest member
BiancaFix3

Latest Threads

Top