Applications that embed python, or use platform-specific python
extensions, may use signals in a way that is currently affected by
`numexpr` launching threads.
For example, it is not uncommon for an application main loop to block
signals when busy, then unblock those signals while waiting for IO.
(see the sigmask argument to `ppoll(2)`)
Signals that arrive during `ppoll(2)` will interrupt the system call,
and allow the application to handle any consequences of that signal
arriving. Normally (in a single threaded process), on delivery of an
externally generated signal such as SIGALRM, SIGCHLD, SIGIO the main
loop will be awoken. IF the thread is otherwise busy, then the signal
will be maintained as pending, and will be delivered when the
application next enters its idle state with `ppoll` again.
`numexpr` creates threads on import. Such threads inherit their signal
masks from the thread that creates them, and, because the import will
generally happen early in the lifetime of a program, all signals are
nominally unblocked in the `numexpr` threads.
Later, if the "main" thread is running with signals blocked when a
signal is sent to the process, the kernel will deliver it to another
thread in the process if it is not currently blocking that signal,
namely, one of the `numexpr` threads.
This means that by creating threads with open signal masks, `numexpr` is
potentially interfering with the normal operation of programs that are
otherwise non-threaded.
Instead, we should block all signals before starting numexpr threads,
and then restore the signal mask as it was, so the `numexpr` threads do
not participate in signal delivery and processing.
Signed-off-by: Peter Edwards <peadar@arista.com>
This eliminates numerous warnings like
warning: #warning "Using deprecated NumPy API, disable it by "#defining NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION" [-Wcpp]