signal() overwriting other signal handlers
Asked Answered
R

2

8

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?

Reposition answered 22/5, 2012 at 12:4 Comment(4)
I don't believe that DLLs and signals are on the same operating system, buddy.Overstay
@DeadMG: You are wrong though, Windows does sort of support SIGINT, msdn.microsoft.com/en-us/library/xdkz3x12(VS.71).aspxNide
@DeadMG: SIGINT isn't, others are. msdn.microsoft.com/en-us/library/xdkz3x12%28v=vs.110%29.aspxStephens
Since signal() is required by Standard C (C89), MSVC must support it. The semantics may be limited, but it must be supported.Foulup
F
11

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.

Foulup answered 22/5, 2012 at 12:18 Comment(0)
G
2

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.

Guillermoguilloche answered 22/5, 2012 at 12:17 Comment(3)
This is true; however, the DLL is being injected.Reposition
Uhm, do you inject the DLL into "arbitrary" processes? Or do you know your target processes internal workings. Because otherwise you risk the stability of them as well. In general, signals and threads don't mix well. Besides, "SIGINT is not supported for any Win32 application. When a CTRL+C interrupt occurs, Win32 operating systems generate a new thread to specifically handle that interrupt. This can cause a single-thread application such as one in UNIX to become multithreaded, resulting in unexpected behavior.".Guillermoguilloche
Yes I do; I understand when sigint is and isn't raised.Reposition

© 2022 - 2024 — McMap. All rights reserved.