signal handling in C

Discussion in 'C Programming' started by subramanian, Dec 15, 2006.

  1. subramanian

    subramanian Guest

    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;
    }
    subramanian, Dec 15, 2006
    #1
    1. Advertising

  2. 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..."

    --
    Richard Heathfield
    "Usenet is a strange place" - dmr 29/7/1999
    http://www.cpax.org.uk
    email: rjh at the above domain, - www.
    Richard Heathfield, Dec 15, 2006
    #2
    1. Advertising

  3. subramanian

    subramanian Guest

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

    On Dec 15, 1:55 am, Richard Heathfield <> wrote:
    > 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..."
    >
    > --
    > Richard Heathfield
    > "Usenet is a strange place" - dmr 29/7/1999http://www.cpax.org.uk
    > email: rjh at the above domain, - www.
    subramanian, Dec 15, 2006
    #3
  4. subramanian

    Chris Torek Guest

    In article <>
    subramanian <> wrote:
    >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.]
    --
    In-Real-Life: Chris Torek, Wind River Systems
    Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
    email: forget about it http://web.torek.net/torek/index.html
    Reading email is like searching for food in the garbage, thanks to spammers.
    Chris Torek, Dec 15, 2006
    #4
  5. 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

    subramanian wrote:
    > 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;
    > }
    vijay kalkoti, Dec 15, 2006
    #5
  6. On Fri, 14 Dec 2006, subramanian wrote:

    > 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);
    }
    Kohn Emil Dan, Dec 15, 2006
    #6
  7. subramanian

    Guest

    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.
    , Dec 15, 2006
    #7
  8. subramanian

    Chris Dollin Guest

    Kohn Emil Dan wrote:

    > On Fri, 14 Dec 2006, subramanian wrote:
    >
    >> 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.


    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.)

    --
    Chris "to heavy to even shortjmp" Dollin
    "We did not have time to find out everything we wanted to know."
    - James Blish, /A Clash of Cymbals/
    Chris Dollin, Dec 15, 2006
    #8
  9. subramanian

    Default User Guest

    Re: signal handling in C - TPA

    vijay kalkoti wrote:

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



    Please don't top-post. Your replies belong following or interspersed
    with properly trimmed quotes. See the majority of other posts in the
    newsgroup, or:
    <http://www.caliburn.nl/topposting.html>
    Default User, Dec 15, 2006
    #9
  10. On Fri, 15 Dec 2006, Chris Dollin wrote:

    > Kohn Emil Dan wrote:

    <snipped>
    >>

    <snipped>
    > 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

    > --
    > Chris "to heavy to even shortjmp" Dollin
    > "We did not have time to find out everything we wanted to know."
    > - James Blish, /A Clash of Cymbals/
    >
    >
    Kohn Emil Dan, Dec 16, 2006
    #10
  11. subramanian

    Richard Bos Guest

    Kohn Emil Dan <> wrote:

    > On Fri, 15 Dec 2006, Chris Dollin 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?


    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
    Richard Bos, Dec 18, 2006
    #11
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Michael Pronath
    Replies:
    1
    Views:
    1,145
    Diez B. Roggisch
    Jan 3, 2005
  2. Jack Orenstein

    threading.Thread vs. signal.signal

    Jack Orenstein, Sep 18, 2005, in forum: Python
    Replies:
    0
    Views:
    457
    Jack Orenstein
    Sep 18, 2005
  3. Weng Tianxiang
    Replies:
    2
    Views:
    643
    Jonathan Bromley
    Jan 30, 2007
  4. Nicolas Moreau
    Replies:
    9
    Views:
    3,103
  5. Peter
    Replies:
    34
    Views:
    1,919
    James Kanze
    Oct 17, 2009
Loading...

Share This Page