Is Linux signal handler possibly be reentered? - Linux

This is a discussion on Is Linux signal handler possibly be reentered? - Linux ; Hi, I made a experiment that is about signal handler reentrancy: binch@binary-ubuntu:/tmp$ cat test.c #include void handler(void) { printf("enter.\n"); *(char *)0 = 0; printf("leave.\n"); } main(void) { signal(SIGSEGV, handler); *(char *)0 = 0; } When running, there is only one ...

+ Reply to Thread
Results 1 to 5 of 5

Thread: Is Linux signal handler possibly be reentered?

  1. Is Linux signal handler possibly be reentered?

    Hi,

    I made a experiment that is about signal handler reentrancy:

    binch@binary-ubuntu:/tmp$ cat test.c
    #include


    void handler(void)
    {
    printf("enter.\n");
    *(char *)0 = 0;
    printf("leave.\n");
    }
    main(void)
    {
    signal(SIGSEGV, handler);

    *(char *)0 = 0;
    }

    When running, there is only one "enter" printed, and the program
    terminated.

    binch@binary-ubuntu:/tmp$ ./test
    enter.
    Segmentation fault

    What I wander is, is it any signal handler that possibly reentered, or,
    a signal handler is intercepted by other signal handler? If two
    handlers are operating same piece of data, this will cause problem just
    like multi threading.

    Any complete manual?

    Thanks.
    ABAI


  2. Re: Is Linux signal handler possibly be reentered?



    On 12月18日, 上午11时33分, "Bin Chen"
    wrote:
    > Hi,
    >
    > I made a experiment that is about signal handler reentrancy:
    >
    > binch@binary-ubuntu:/tmp$ cat test.c
    > #include
    >
    > void handler(void)
    > {
    > printf("enter.\n");
    > *(char *)0 = 0;
    > printf("leave.\n");}main(void)
    > {
    > signal(SIGSEGV, handler);
    >
    > *(char *)0 = 0;
    >
    > }When running, there is only one "enter" printed, and the program
    > terminated.
    >
    > binch@binary-ubuntu:/tmp$ ./test
    > enter.
    > Segmentation fault
    >
    > What I wander is, is it any signal handler that possibly reentered, or,
    > a signal handler is intercepted by other signal handler? If two
    > handlers are operating same piece of data, this will cause problem just
    > like multi threading.
    >
    > Any complete manual?
    >
    > Thanks.
    > ABAI


    Find a paper: http://lcamtuf.coredump.cx/signals.txt


  3. Re: Is Linux signal handler possibly be reentered?

    Bin Chen wrote:
    > Hi,
    >
    > I made a experiment that is about signal handler reentrancy:
    >
    > binch@binary-ubuntu:/tmp$ cat test.c
    > #include
    >
    >
    > void handler(void)
    > {
    > printf("enter.\n");
    > *(char *)0 = 0;
    > printf("leave.\n");
    > }
    > main(void)
    > {
    > signal(SIGSEGV, handler);
    >
    > *(char *)0 = 0;
    > }
    >
    > When running, there is only one "enter" printed, and the program
    > terminated.
    >
    > binch@binary-ubuntu:/tmp$ ./test
    > enter.
    > Segmentation fault
    >
    > What I wander is, is it any signal handler that possibly reentered, or,
    > a signal handler is intercepted by other signal handler? If two
    > handlers are operating same piece of data, this will cause problem just
    > like multi threading.
    >
    > Any complete manual?


    reentrant or not, it is not safe to call printf in a signal handler.

  4. Re: Is Linux signal handler possibly be reentered?

    Hello Abai,

    > I made a experiment that is about signal handler reentrancy:
    >
    > binch@binary-ubuntu:/tmp$ cat test.c
    > #include
    >
    >
    > void handler(void)
    > {
    > printf("enter.\n");
    > *(char *)0 = 0;
    > printf("leave.\n");
    > }
    > main(void)
    > {
    > signal(SIGSEGV, handler);
    >
    > *(char *)0 = 0;
    > }


    First, two remarks regarding your program:

    1) the signal handler's prototype should be:
    void handler (int signo)

    2) Modern programs should use /sigaction()/ instead of /signal()/,
    which provides a more comprehensive and reliable mechanism for
    controlling signals.


    > When running, there is only one "enter" printed, and the program
    > terminated.
    >
    > binch@binary-ubuntu:/tmp$ ./test
    > enter.
    > Segmentation fault
    >
    > What I wander is, is it any signal handler that possibly reentered, or,
    > a signal handler is intercepted by other signal handler? If two
    > handlers are operating same piece of data, this will cause problem just
    > like multi threading.
    >
    > Any complete manual?


    On Linux, calling /signal(SIGNAL, handler)/ is equivalent to call
    /sigaction()/ with the following sigaction structure act:
    act.sa_handler = handler
    act.sa_mask = SIGNAL
    act.sa_flags = SA_RESTART

    As consequence, the signal SIGSEGV is blocked during the invocation of
    your signal handler. SUSv3 is quite explicit what happens if a SIGSEGV
    exception occurs while that same SIGSEGV is blocked:

    If any of the SIGFPE, SIGILL, SIGSEGV, or SIGBUS signals are generated
    while they are blocked, the result is undefined, unless the signal was
    generated by the kill() function, the sigqueue() function, or the
    raise() function.


    It means that the result of generating a SIGSEGV exception in your case
    is "undefined". On your distro, the implementation choose to ignore the
    blocking of SIGSEGV and let the default course happens (core dump +
    process termination).

    It seems however that on newer Linux/Glibc, the behavior is different.
    For instance, running your program on my Fedora Core 5, I get the
    endless loop you would expect. I don't know however if this the result
    of a change in the glibc, or a change in the Linux kernel.

    HTH,
    Loic.


  5. Re: Is Linux signal handler possibly be reentered?

    Hello Nils,

    > > #include
    > >
    > >
    > > void handler(void)
    > > {
    > > printf("enter.\n");
    > > *(char *)0 = 0;
    > > printf("leave.\n");
    > > }
    > > main(void)
    > > {
    > > signal(SIGSEGV, handler);
    > >
    > > *(char *)0 = 0;
    > > }
    > >
    > > When running, there is only one "enter" printed, and the program
    > > terminated.
    > >
    > > binch@binary-ubuntu:/tmp$ ./test
    > > enter.
    > > Segmentation fault
    > >
    > > What I wander is, is it any signal handler that possibly reentered, or,
    > > a signal handler is intercepted by other signal handler? If two
    > > handlers are operating same piece of data, this will cause problem just
    > > like multi threading.
    > >
    > > Any complete manual?

    >
    > reentrant or not, it is not safe to call printf in a signal handler.


    Technically speaking, the program below is absolutely correct from a
    SUS standpoint. As quoted by SUSv3:

    All functions not in the above table [async-signal-safe functions] are
    considered to be unsafe with respect to signals. In the presence of
    signals, all functions defined by this volume of IEEE Std 1003.1-2001
    shall behave as defined when called from or interrupted by a
    signal-catching function, with a single exception: when a signal
    interrupts an unsafe function and the signal-catching function calls an
    unsafe function, the behavior is undefined.


    That means, you can perfectly call /printf()/ in signal handler, as
    long as you ensure that the function /printf()/ has not been
    interrupted when your handler is called. This is obviously the case for
    the program mentioned here.

    I agree however with you: for non trivial programs, this is almost
    impossible[1] to achieve, so your advice applies. And following your
    advice, you're always on the 'safe side'.

    Cheers,
    Loic.

    [1] Well it is possible to achieve. But that's really awkward, and I
    believe it's just easier to just restrict himself in using
    async-signal-safe functions in signal handler.


+ Reply to Thread