WG14 threadsafe signals
Loading...
Searching...
No Matches
thrd_signal_handle.h File Reference
#include "config.h"
#include <signal.h>
#include <stdbool.h>
#include <stdint.h>
Include dependency graph for thrd_signal_handle.h:

Go to the source code of this file.

Classes

union  thrd_raised_signal_info_value
 User defined value. More...
 
struct  thrd_raised_signal_info
 A platform independent subset of siginfo_t. More...
 

Typedefs

typedef int thrd_raised_signal_error_code_t
 Typedef to a system specific error code type.
 
typedef struct __siginfo thrd_raised_signal_info_siginfo_t
 A placeholder type for an OS specific siginfo_t * (POSIX) or PEXCEPTION_RECORD (Windows)
 
typedef struct ucontext_t thrd_raised_signal_info_context_t
 A placeholder type for an OS specific ucontext_t (POSIX) or PCONTEXT (Windows)
 

Enumerations

enum  thrd_signal_decision_t { thrd_signal_decision_next_decider , thrd_signal_decision_resume_execution , thrd_signal_decision_invoke_recovery }
 The decision taken by the decider function. More...
 

Functions

union thrd_raised_signal_info_value() thrd_signal_func_t (union thrd_raised_signal_info_value)
 The type of the guarded function.
 
union thrd_raised_signal_info_value() thrd_signal_recover_t (const struct thrd_raised_signal_info *)
 The type of the function called to recover from a signal being raised in a guarded section.
 
enum thrd_signal_decision_t() thrd_signal_decide_t (struct thrd_raised_signal_info *)
 The type of the function called when a signal is raised. Returns a decision of how to handle the signal.
 
const sigset_t * synchronous_sigset (void)
 THREADSAFE ASYNC-SIGNAL-SAFE The set of synchronous signals for this platform.
 
const sigset_t * asynchronous_nondebug_sigset (void)
 THREADSAFE ASYNC-SIGNAL-SAFE The set of non-debug asynchronous signals for this platform.
 
const sigset_t * asynchronous_debug_sigset (void)
 THREADSAFE ASYNC-SIGNAL-SAFE The set of debug asynchronous signals for this platform.
 
union thrd_raised_signal_info_value thrd_signal_invoke (const sigset_t *signals, thrd_signal_func_t guarded, thrd_signal_recover_t recovery, thrd_signal_decide_t decider, union thrd_raised_signal_info_value value)
 THREADSAFE USUALLY ASYNC-SIGNAL-SAFE Installs a thread-local signal guard for the calling thread, and calls the guarded function guarded.
 
bool thrd_signal_raise (int signo, thrd_raised_signal_info_siginfo_t *raw_info, thrd_raised_signal_info_context_t *raw_context)
 THREADSAFE USUALLY ASYNC-SIGNAL-SAFE Call OUR currently installed signal decider for a signal (POSIX), or raise a Win32 structured exception (Windows), returning false if we have no decider installed for that signal.
 
void * threadsafe_signals_install (const sigset_t *guarded, int version)
 THREADSAFE Installs, and potentially enables, the global signal handlers for the signals specified by guarded. Each signal installed is threadsafe reference counted, so this is safe to call from multiple threads or instantiate multiple times.
 
int threadsafe_signals_uninstall (void *i)
 THREADSAFE Uninstall a previously installed signal guard.
 
int threadsafe_signals_uninstall_system (int version)
 THREADSAFE Uninstall a previously system installed signal guard.
 
void * signal_decider_create (const sigset_t *guarded, bool callfirst, thrd_signal_decide_t decider, union thrd_raised_signal_info_value value)
 THREADSAFE NOT REENTRANT Create a global signal continuation decider. Threadsafe with respect to other calls of this function, but not reentrant i.e. modifying the global signal continuation decider registry whilst inside a global signal continuation decider is racy, and in any case definitely not async signal handler safe. Called after all thread local handling is exhausted. Note that what you can safely do in the decider function is extremely limited, only async signal safe functions may be called.
 
int signal_decider_destroy (void *decider)
 THREADSAFE NOT REENTRANT Destroy a global signal continuation decider. Threadsafe with respect to other calls of this function, but not reentrant i.e. do not call whilst inside a global signal continuation decider.
 

Typedef Documentation

◆ thrd_raised_signal_error_code_t

Typedef to a system specific error code type.

Definition at line 103 of file thrd_signal_handle.h.

◆ thrd_raised_signal_info_context_t

typedef struct ucontext_t thrd_raised_signal_info_context_t

A placeholder type for an OS specific ucontext_t (POSIX) or PCONTEXT (Windows)

Definition at line 124 of file thrd_signal_handle.h.

◆ thrd_raised_signal_info_siginfo_t

typedef struct __siginfo thrd_raised_signal_info_siginfo_t

A placeholder type for an OS specific siginfo_t * (POSIX) or PEXCEPTION_RECORD (Windows)

Definition at line 114 of file thrd_signal_handle.h.

Enumeration Type Documentation

◆ thrd_signal_decision_t

The decision taken by the decider function.

Enumerator
thrd_signal_decision_next_decider 

We have decided to do nothing.

thrd_signal_decision_resume_execution 

We have fixed the cause of the signal, please resume execution.

thrd_signal_decision_invoke_recovery 

Thread local signal deciders only: reset the stack and local state to entry to thrd_signal_invoke(), and call the recovery function.

Definition at line 159 of file thrd_signal_handle.h.

Function Documentation

◆ asynchronous_debug_sigset()

const sigset_t * asynchronous_debug_sigset ( void  )
extern

THREADSAFE ASYNC-SIGNAL-SAFE The set of debug asynchronous signals for this platform.

Debug asynchronous signals are those which are delivered by the system to notify the process about some event which defaults to resulting in a core dump. This set can include platform-specific additions, however at least these POSIX signals are within this set:

SIGQUIT SIGTRAP SIGXCPU SIGXFSZ

◆ asynchronous_nondebug_sigset()

const sigset_t * asynchronous_nondebug_sigset ( void  )
extern

THREADSAFE ASYNC-SIGNAL-SAFE The set of non-debug asynchronous signals for this platform.

Non-debug asynchronous signals are those which are delivered by the system to notify the process about some event which does not default to resulting in a core dump. This set can include platform-specific additions, however at least these POSIX signals are within this set:

SIGALRM SIGCHLD SIGCONT SIGHUP SIGINT SIGKILL SIGSTOP SIGTERM SIGTSTP SIGTTIN SIGTTOU SIGUSR1 SIGUSR2 SIGPOLL SIGPROF SIGURG SIGVTALRM

◆ signal_decider_create()

void * signal_decider_create ( const sigset_t *  guarded,
bool  callfirst,
thrd_signal_decide_t  decider,
union thrd_raised_signal_info_value  value 
)
extern

THREADSAFE NOT REENTRANT Create a global signal continuation decider. Threadsafe with respect to other calls of this function, but not reentrant i.e. modifying the global signal continuation decider registry whilst inside a global signal continuation decider is racy, and in any case definitely not async signal handler safe. Called after all thread local handling is exhausted. Note that what you can safely do in the decider function is extremely limited, only async signal safe functions may be called.

Returns
An opaque pointer to the registered decider. NULL if malloc failed.
Parameters
guardedThe set of signals to be guarded against.
callfirstTrue if this decider should be called before any other. Otherwise call order is in the order of addition.
deciderA decider function, which must return true if execution is to resume, false if the next decider function should be called.
valueA user supplied value to set in the raised_signal_info passed to the decider callback.

◆ signal_decider_destroy()

int signal_decider_destroy ( void *  decider)
extern

THREADSAFE NOT REENTRANT Destroy a global signal continuation decider. Threadsafe with respect to other calls of this function, but not reentrant i.e. do not call whilst inside a global signal continuation decider.

Returns
True if recognised and thus removed.

◆ synchronous_sigset()

const sigset_t * synchronous_sigset ( void  )
extern

THREADSAFE ASYNC-SIGNAL-SAFE The set of synchronous signals for this platform.

Synchronous signals are those which can be raised by a thread in the course of its execution. This set can include platform-specific additions, however at least these POSIX signals are within this set:

SIGABRT SIGBUS SIGFPE SIGILL SIGPIPE SIGSEGV SIGSYS

◆ thrd_signal_decide_t()

enum thrd_signal_decision_t() thrd_signal_decide_t ( struct thrd_raised_signal_info )

The type of the function called when a signal is raised. Returns a decision of how to handle the signal.

◆ thrd_signal_func_t()

union thrd_raised_signal_info_value() thrd_signal_func_t ( union thrd_raised_signal_info_value  )

The type of the guarded function.

◆ thrd_signal_invoke()

union thrd_raised_signal_info_value thrd_signal_invoke ( const sigset_t *  signals,
thrd_signal_func_t  guarded,
thrd_signal_recover_t  recovery,
thrd_signal_decide_t  decider,
union thrd_raised_signal_info_value  value 
)
extern

THREADSAFE USUALLY ASYNC-SIGNAL-SAFE Installs a thread-local signal guard for the calling thread, and calls the guarded function guarded.

Returns
The value returned by guarded, or recovery.
Parameters
signalsThe set of signals to guard against.
guardedA function whose execution is to be guarded against signal raises.
recoveryA function to be called if a signal is raised.
deciderA function to be called to decide whether to recover from the signal and continue the execution of the guarded routine, or to abort and call the recovery routine.
valueA value to supply to the guarded routine.

By "usually async signal safe" we mean that if any function from this library has been called from the called from the calling thread, this is async signal safe. If you need to set up this library for a calling thread without doing anything else, calling thrd_signal_raise(0, nullptr, nullptr), this will ensure the calling thread's thread local state is set up and return immediately doing nothing else.

◆ thrd_signal_raise()

bool thrd_signal_raise ( int  signo,
thrd_raised_signal_info_siginfo_t raw_info,
thrd_raised_signal_info_context_t raw_context 
)
extern

THREADSAFE USUALLY ASYNC-SIGNAL-SAFE Call OUR currently installed signal decider for a signal (POSIX), or raise a Win32 structured exception (Windows), returning false if we have no decider installed for that signal.

Note that on POSIX, we fetch OUR currently installed signal decider and call it directly. This allows us to supply custom raw_info and raw_context. Each decider in our chain will be invoked in turn until we reach whatever the signal handler was when this library was first initialised, and we hand off to that handler. If that handler was defaulted and the default handling is not to ignore, we reset the handler installation and execute pthread_kill(pthread_self(), signo) in order to invoke the default handling.

It is important to note that this call does not raise signals itself except in that final handling step as just described. Therefore, if your code overwrites the signal handlers installed by this library with a custom handler, and you wish to pass on signal handling to this library, this is the right API to call to do that.

On Windows, Win32 structured exceptions are capable of being used directly and so we do on that platform always call RaiseException().

By "usually async signal safe" we mean that if any function from this library has been called from the called from the calling thread, this is async signal safe. If you need to set up this library for a calling thread without doing anything else, specify zero for signo, this will ensure the calling thread's thread local state is set up and return immediately doing nothing else.

◆ thrd_signal_recover_t()

union thrd_raised_signal_info_value() thrd_signal_recover_t ( const struct thrd_raised_signal_info )

The type of the function called to recover from a signal being raised in a guarded section.

◆ threadsafe_signals_install()

void * threadsafe_signals_install ( const sigset_t *  guarded,
int  version 
)
extern

THREADSAFE Installs, and potentially enables, the global signal handlers for the signals specified by guarded. Each signal installed is threadsafe reference counted, so this is safe to call from multiple threads or instantiate multiple times.

If guarded is null, all the standard POSIX signals are used. version is reserved for future use, and should be zero.

POSIX only

Any existing global signal handlers are replaced with a filtering signal handler, which checks if the current kernel thread has installed a signal guard, and if so executes the guard. If no signal guard has been installed for the current kernel thread, global signal continuation handlers are executed. If none claims the signal, the previously installed signal handler is called.

After the new signal handlers have been installed, the guarded signals are globally enabled for all threads of execution. Be aware that the handlers are installed with SA_NODEFER to avoid the need to perform an expensive syscall when a signal is handled. However this may also produce surprise e.g. infinite loops.

Warning
This class is threadsafe with respect to other concurrent executions of itself, but is NOT threadsafe with respect to other code modifying the global signal handlers.

◆ threadsafe_signals_uninstall()

int threadsafe_signals_uninstall ( void *  i)
extern

THREADSAFE Uninstall a previously installed signal guard.

◆ threadsafe_signals_uninstall_system()

int threadsafe_signals_uninstall_system ( int  version)
extern

THREADSAFE Uninstall a previously system installed signal guard.