sbcl doesn't offer a way to reinstate a signal handler broken by foreign code

Bug #548612 reported by Nikodemus Siivola on 2010-03-26
This bug affects 2 people
Affects Status Importance Assigned to Milestone

Bug Description

Foreign libraries can mess with SBCL installed signal handlers. INSTALL-HANDLER cannot be used to recover from such situations as it doesn't call sigaction() again.

Something like WITH-RECOVERED-SIGNAL-HANDLERS would be good.

Brett van de Sande (bvds) wrote :

In C, this would look something like:

#include <signal.h>
struct sigaction old_action;
sigaction (SIGALRM, NULL, &old_action);

  /* call foreign library */

sigaction (SIGALRM, &old_action, NULL);

I don't know whether it warrants its own bug, but on a related note, deferrable signals blocked in foreign libraries will cause a sanity check done by interrupts.c to fail.

all_signals_blocked_p will drop SBCL into ldb if only one signal from a set is blocked. This is a problem for programs using foreign libraries that may block signals during a function call (libpq's PQsendQuery will lead to sigpipe being blocked is how I stumbled upon this). The workaround right now is to block all deferrable signals during foreign function calls, but I would rather have a way to somehow signify to SBCL that I expect sigpipe (or any deferrable signal) to be blocked by a foreign function call, but other signals should make their way back to SBCL.

Gábor Melis (melisgl) wrote :

Theoretical view: libraries messing with signal handlers is in bad style as different signal handling strategies don't compose at all so fix the library. More practically, are you sure that INSTALL-HANDLER (should be called via ENABLE-INTERRUPT) does not call sigaction again? As far as I can tell by reading install_handler that's only happens when a "low level" interrupt handler was installed.

Be them low level or not these are often critical enough that removing the SBCL handler even for a short while can compromise the image (e.g. SIGSEGV) or some functionality (e.g. SIGALRM, ). So which signal are we talking about here?

Gábor Melis (melisgl) wrote :

To Andrew.

libpq blocking sigpipe will render timers and interrupt-thread (targeting that thread) ineffective. One possible solution is to ignore sigpipe, use a different signal for interrupt-thread and ((remove sigpipe from the deferrable set) or (remove the check_deferrables_unblocked call)).

When choosing another signal instead of sigpipe one must consider what this commit message explains: use a signal for SIG_STOP_FOR_GC > SIGSEGV on Linux

    On Linux a signal generated by pthread_kill() with a signum that's
    lower than SIGSEGV can be delivered before a synchronously triggered
    SIGSEGV. This means that the sigsegv handler will be invoked with its
    context pointing to the handler for the signal that pthread_kill()
    sent. It's not really specific to SIGSEGV, it's the same for any
    synchronously generated signal.

    To work around this, we must never pthread_kill() with a signal with a
    lower signum than any of the synchronously triggered signals that we
    use: SIGTRAP, SIGSEGV, etc. In practice, currently we only send
    SIGPIPE to indicate that the thread interruption queue may need to be
    looked at and SIG_STOP_FOR_GC that's defined as SIGUSR1 currently.

    With SIGUSR1 being 10 and SIGSEGV 11 this can make
    handle_guard_page_triggered lose badly if GC wants to stop the thread
    at the same time. So let's use SIGUSR2 instead that's 12. Do the same
    on other OSes they may have same bug.

    See thread "Signal delivery order" from 2009-03-14 on
    <email address hidden>:

To post a comment you must log in.
This report contains Public information  Edit
Everyone can see this information.

Other bug subscribers