Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

signal() overwriting other signal handlers

Tags:

c++

dll

sigint

Does the signal() function overwrite other signal calls a process might have set up? I.e. if a SIGINT handler has been setup by a process, and a DLL calls signal(SIGINT,xxx) to handle its own termination code, does the original SIGINT handler get disabled?

like image 787
Qix - MONICA WAS MISTREATED Avatar asked May 22 '12 12:05

Qix - MONICA WAS MISTREATED


People also ask

Does signal () call the signal handler?

signal() sets the disposition of the signal signum to handler, which is either SIG_IGN, SIG_DFL, or the address of a programmer- defined function (a "signal handler"). If the signal signum is delivered to the process, then one of the following happens: * If the disposition is set to SIG_IGN, then the signal is ignored.

Can signal handlers be interrupted by other signal handlers?

Signal handlers can be interrupted by signals, including their own. If a signal is not reset before its handler is called, the handler can interrupt its own execution. A handler that always successfully executes its code despite interrupting itself or being interrupted is async-signal-safe.

Can you override Sigkill?

Unlike SIGINT, SIGKILL does not just interrupt the program, it terminates it without further question. More importantly, SIGKILL cannot be overridden by a program, so it will always work.

What's the difference between signal () and sigaction ()? Explain with an example?

The signal() function does not (necessarily) block other signals from arriving while the current handler is executing; sigaction() can block other signals until the current handler returns. The signal() function (usually) resets the signal action back to SIG_DFL (default) for almost all signals.


2 Answers

The signal() call:

  1. Installs the handler you specify as a new signal handler, and
  2. Tells you what the old handler was.

The new handler will be called instead of the old one. If you want to chain them, you need to do something like:

    typedef void (*Handler)(int signum);

    static Handler old_int_handler = SIG_IGN;

    static void int_handler(int signum)    /* New signal handler */
    {
        /* ...do your signal handling... */
        if (old_int_handler != SIG_IGN && old_int_handler != SIG_DFL)
            (*old_int_handler)(signum);
    }

    static void set_int_handler(void)  /* Install new handler */
    {
        Handler old = signal(SIGINT, SIG_IGN);
        if (old != SIG_IGN)
        {
            old_int_handler = old;
            signal(SIGINT, int_handler);
        }
    }

    static void rst_int_handler(void)    /* Restore original handler */
    {
        Handler old = signal(SIGINT, SIG_IGN);
        if (old == int_handler)
        {
            signal(SIGINT, old_int_handler);
            old_int_handler = SIG_IGN;
        }
    }

    void another_function()
    {
        /* ... */
        set_int_handler();
        /* ... */
        rst_int_handler();
        /* ... */
    }

If interrupts were being ignored, this keeps them ignored. If interrupts were being handled by a user-defined interrupt handler, then this calls your signal handling code and the original signal handling code.

Note that the advice from Christian.K about not handling signals in a DLL (shared library) is also relevant and valid. The description above assumes you decide to ignore that advice.

like image 67
Jonathan Leffler Avatar answered Sep 29 '22 12:09

Jonathan Leffler


This is not a "literal" answer to your question, but a recommendation: You shouldn't do this in a DLL.

It is unexpected and often annoying for the application that uses the DLL. A DLL should (normally) be "passive" and only provide functions for the application to call.

So rather provide a public function from your DLL that applications are required to call e.g. MyDllCleanup(). Then let the application decide how it calls that function (via a signal handler or other). BTW, the same goes for initialization: rather than relying on DllMain (or _init/_fini with libdl on UNIX) provide explicit functions for applications to call.

like image 29
Christian.K Avatar answered Sep 29 '22 13:09

Christian.K