1

My Application had already configured a SIGTERM handler. Ex:

Signal(SIGTERM, &signalHandler);

I want to do some processing before shutdown and I cannot do change in existing signal handler. To do my processing, I placed a hook like this configured my handler as

signal(SIGTERM, &mySignalHandler);

mySignalHandler calls signalHandler later after doing its processing to make system unaffected even after the hook.

Now, considering the fact that mySignalHandler will be invoked, It works when kill $pid once. But if I do it twice or more time. signalHandler gets called. As far as I know SIG_DFL should be performed in this case.

Anybody knows the reason for this.

I am using “Red Hat Enterprise Linux AS release 4 (Nahant Update 8)”

[EDIT]:strange behaviour faced with test program

#undef _GNU_SOURCE
using namespace std;

volatile sig_atomic_t signalHandlerVar_ = false;
volatile sig_atomic_t signalHandlerSecondVar_ = false;

extern "C" void signalHandler(int)
{
    signalHandlerVar_ = true;
}

extern "C" void signalHandlerSecond(int value)
{
    signalHandlerSecondVar_ = true;
}

void* threadFunc(void*)
{
    while(1)
    {
        if(signalHandlerVar_)
        {
            cout<<"signalHandler_ "<<signalHandlerVar_<<endl;
            signalHandlerVar_ = false;
        }

        if(signalHandlerSecondVar_)
        {
            cout<<"signalHandlerSecond_ "<<signalHandlerSecondVar_<<endl;
            signalHandlerSecondVar_ = false;
        }
    }

    return NULL;
}

int main()
{
    ::signal(SIGTERM, &signalHandler);
    ::signal(SIGTERM, &signalHandlerSecond);
    pthread_t thread;

    if(pthread_create(&thread, NULL, &threadFunc, NULL))
    {
        cout<<"pthread create failed"<<endl;
        return 1;
    }
    pthread_join(thread, NULL);
}

Here problem i am facing, on every kill $pid it calls signalHandlerSecond.as i am using #undef _GNU_SOURCE and tried #undef _BSD_SOURCE.But it should reset it to SIG_DFL.

Can anybody suggest where i am doing wrong?

Nitin Singh
  • 41
  • 1
  • 4
  • [The man page](http://linux.die.net/man/2/signal) says that resetting to SIG_DFL is the original Unix behavior. On Linux, it either has BSD behavior (if `_BSD_SOURCE`) or system V behavior (if source is compiled to be strictly standard). If you are compiling with `-std=cXX` as opposed to `-std=gnuXX`, then perhaps you could give compiling with GNU features a try, or define `_BSD_SOURCE`. – Shahbaz May 22 '14 at 11:48

2 Answers2

2

From signal

DESCRIPTION

The behavior of signal() varies across UNIX versions, and has also varied historically across different versions of Linux. Avoid its use: use sigaction(2) instead. See Portability below.
...
If the signal signum is delivered to the process, then one of the following happens:
- ...
- ...
- If the disposition is set to a function, then first either the disposition is reset to SIG_DFL, or the signal is blocked (see Portability below), and then handler is called with argument signum. If invocation of the handler caused the signal to be blocked, then the signal is unblocked upon return from the handler.

On Linux, it depends on how you compile your source. Since your program isn't aborted from any following kill, I suspect it uses the BSD semantics as described later under Portability

The situation on Linux is as follows:

  * The kernel's signal() system call provides System V semantics.

  * By default, in glibc 2 and later, the signal() wrapper function
     does not invoke the kernel system call.  Instead, it calls
     sigaction(2) using flags that supply BSD semantics.  This default
     behavior is provided as long as the _BSD_SOURCE feature test macro
     is defined.  By default, _BSD_SOURCE is defined; it is also
     implicitly defined if one defines _GNU_SOURCE, and can of course be
     explicitly defined.

    On glibc 2 and later, if the _BSD_SOURCE feature test macro is not
     defined, then signal() provides System V semantics.  (The default
     implicit definition of _BSD_SOURCE is not provided if one invokes
     gcc(1) in one of its standard modes (-std=xxx or -ansi) or defines
     various other feature test macros such as _POSIX_SOURCE,
     _XOPEN_SOURCE, or _SVID_SOURCE; see feature_test_macros(7).)

To force System V behaviour, you need to define one of _POSIX_SOURCE, _XOPEN_SOURCE, or _SVID_SOURCE, e.g.

gcc -D_SVID_SOURCE -Wall -g -pthread test.c

This doesn't seem to work with g++, though. When you compile with

g++ -D_SVID_SOURCE -Wall -g -pthread test.cpp

you still get the BSD behaviour. Adding -v

g++ -v -D_SVID_SOURCE -Wall -g -pthread test.cpp

reveals

/usr/lib/gcc/x86_64-linux-gnu/4.6/cc1plus -quiet -v -imultilib . -imultiarch x86_64-linux-gnu -D_GNU_SOURCE -D_REENTRANT -D _SVID_SOURCE test.cpp -quiet -dumpbase test.cpp -mtune=generic -march=x86-64 -auxbase a -g -Wall -version -fstack-protector -o /tmp/cc3MpiO2.s

which is not present, when compiling with gcc. You can suppress this with an additional -U_GNU_SOURCE

g++ -U_GNU_SOURCE -D_SVID_SOURCE -Wall -g -pthread test.cpp

Finally, this gives us System V behaviour, which means the signal handler is reset to SIG_DFL after the first signal delivery.

Olaf Dietsche
  • 72,253
  • 8
  • 102
  • 198
  • "the library resets the signal so that the default action is performed if the same signal occurs again".So signalHandler should not be caleed.it gives me the impression that after disposition it sets SIG_DFL as the one i had configured earlier.So, doest kernel do such book-keeping. – Nitin Singh May 22 '14 at 13:00
  • The kernel doesn't do any book-keeping. It stores only one signal handler per signal. `signal` returns the previous signal handler. – Olaf Dietsche May 22 '14 at 13:21
  • Your quote describes the System V behaviour. This is not what Linux does, unless you explicitly request by doing `#undef _BSD_SOURCE` or use `-std=...`. Try yourself and compile your program with System V semantics. Then you will see the behaviour, you quoted. – Olaf Dietsche May 22 '14 at 13:27
  • edidted the post, tried with Sysytem V semantic,now facing some strange issue – Nitin Singh May 23 '14 at 09:08
  • 1
    It seems `_BSD_SOURCE` is not explicitly defined, but implicitly through `_GNU_SOURCE`, so the man page is not correct in this case. Please see updated answer. – Olaf Dietsche May 23 '14 at 10:26
0

At the end of your function mySignalHandler(), you have to call signal() again :

The first time (anywhere in your code) :

signal(SIGTERM, &mySignalHandler);

Then in your function :

void mySignalHandler() {
    //your code here

    signal(SIGTERM, &mySignalHandler);
}

Like this, the next time SIGTERM is catched, the program will enter in mySignalHandler()

Hope it's help you.

Simon PA
  • 748
  • 13
  • 26