@ -4,38 +4,39 @@
/* XXX Signals should be recorded per thread, now we have thread state. */
# include "Python.h"
# include "pycore_atomic.h"
# include "pycore_call.h"
# include "pycore_ceval.h"
# include "pycore_pyerrors.h"
# include "pycore_pylifecycle.h"
# include "pycore_pystate.h" // _PyThreadState_GET()
# include "pycore_atomic.h" // _Py_atomic_int
# include "pycore_call.h" // _PyObject_Call()
# include "pycore_ceval.h" // _PyEval_SignalReceived()
# include "pycore_moduleobject.h" // _PyModule_GetState()
# include "pycore_pyerrors.h" // _PyErr_SetString()
# include "pycore_pylifecycle.h" // NSIG
# include "pycore_pystate.h" // _PyThreadState_GET()
# ifndef MS_WINDOWS
# include "posixmodule.h"
# include "posixmodule.h"
# endif
# ifdef MS_WINDOWS
# include "socketmodule.h" /* needed for SOCKET_T */
# include "socketmodule.h" /* needed for SOCKET_T */
# endif
# ifdef MS_WINDOWS
# include <windows.h>
# ifdef HAVE_PROCESS_H
# include <process.h>
# endif
# include <windows.h>
# ifdef HAVE_PROCESS_H
# include <process.h>
# endif
# endif
# ifdef HAVE_SIGNAL_H
# include <signal.h>
# include <signal.h>
# endif
# ifdef HAVE_SYS_SYSCALL_H
# include <sys/ syscall.h>
# include <sys / syscall.h>
# endif
# ifdef HAVE_SYS_STAT_H
# include <sys/ stat.h>
# include <sys / stat.h>
# endif
# ifdef HAVE_SYS_TIME_H
# include <sys/ time.h>
# include <sys / time.h>
# endif
# if defined(HAVE_PTHREAD_SIGMASK) && !defined(HAVE_BROKEN_PTHREAD_SIGMASK)
@ -47,7 +48,7 @@
# endif
# ifndef SIG_ERR
# define SIG_ERR ((PyOS_sighandler_t)(-1))
# define SIG_ERR ((PyOS_sighandler_t)(-1))
# endif
# include "clinic/signalmodule.c.h"
@ -124,27 +125,52 @@ static volatile struct {
/* Speed up sigcheck() when none tripped */
static _Py_atomic_int is_tripped ;
static PyObject * DefaultHandler ;
static PyObject * IgnoreH andler;
typedef struct {
PyObject * default_h andler ;
PyObject * ignore_handler ;
# ifdef MS_WINDOWS
static HANDLE sigint_event = NULL ;
HANDLE sigint_event ;
# endif
} signal_state_t ;
/ / State shared by all Python interpreters
static signal_state_t signal_global_state = { 0 } ;
# if defined(HAVE_GETITIMER) || defined(HAVE_SETITIMER)
static PyObject * ItimerError ;
# define PYHAVE_ITIMER_ERROR
# endif
typedef struct {
PyObject * default_handler ; / / borrowed ref ( signal_global_state )
PyObject * ignore_handler ; / / borrowed ref ( signal_global_state )
# ifdef PYHAVE_ITIMER_ERROR
PyObject * itimer_error ;
# endif
} _signal_module_state ;
Py_LOCAL_INLINE ( PyObject * )
get_handler ( int i ) {
get_handler ( int i )
{
return ( PyObject * ) _Py_atomic_load ( & Handlers [ i ] . func ) ;
}
Py_LOCAL_INLINE ( void )
SetHandler ( int i , PyObject * func ) {
set_handler ( int i , PyObject * func )
{
_Py_atomic_store ( & Handlers [ i ] . func , ( uintptr_t ) func ) ;
}
static inline _signal_module_state *
get_signal_state ( PyObject * module )
{
void * state = _PyModule_GetState ( module ) ;
assert ( state ! = NULL ) ;
return ( _signal_module_state * ) state ;
}
# ifdef HAVE_GETITIMER
/* auxiliary functions for setitimer */
static int
@ -359,8 +385,10 @@ signal_handler(int sig_num)
errno = save_errno ;
# ifdef MS_WINDOWS
if ( sig_num = = SIGINT )
SetEvent ( sigint_event ) ;
if ( sig_num = = SIGINT ) {
signal_state_t * state = & signal_global_state ;
SetEvent ( state - > sigint_event ) ;
}
# endif
}
@ -459,6 +487,7 @@ static PyObject *
signal_signal_impl ( PyObject * module , int signalnum , PyObject * handler )
/*[clinic end generated code: output=b44cfda43780f3a1 input=deee84af5fa0432c]*/
{
_signal_module_state * modstate = get_signal_state ( module ) ;
PyObject * old_handler ;
void ( * func ) ( int ) ;
# ifdef MS_WINDOWS
@ -493,10 +522,10 @@ signal_signal_impl(PyObject *module, int signalnum, PyObject *handler)
" signal number out of range " ) ;
return NULL ;
}
if ( handler = = IgnoreH andler) {
if ( handler = = modstate - > ignore_h andler) {
func = SIG_IGN ;
}
else if ( handler = = DefaultH andler) {
else if ( handler = = modstate - > default_h andler) {
func = SIG_DFL ;
}
else if ( ! PyCallable_Check ( handler ) ) {
@ -519,7 +548,7 @@ signal_signal_impl(PyObject *module, int signalnum, PyObject *handler)
}
old_handler = get_handler ( signalnum ) ;
SetH andler( signalnum , Py_NewRef ( handler ) ) ;
set_h andler( signalnum , Py_NewRef ( handler ) ) ;
if ( old_handler ! = NULL ) {
return old_handler ;
@ -831,7 +860,6 @@ PySignal_SetWakeupFd(int fd)
# ifdef HAVE_SETITIMER
/*[clinic input]
signal . setitimer
@ -853,8 +881,9 @@ signal_setitimer_impl(PyObject *module, int which, PyObject *seconds,
PyObject * interval )
/*[clinic end generated code: output=65f9dcbddc35527b input=de43daf194e6f66f]*/
{
struct itimerval new ;
_signal_module_state * modstate = get_signal_state ( module ) ;
struct itimerval new ;
if ( timeval_from_double ( seconds , & new . it_value ) < 0 ) {
return NULL ;
}
@ -865,18 +894,16 @@ signal_setitimer_impl(PyObject *module, int which, PyObject *seconds,
/* Let OS check "which" value */
struct itimerval old ;
if ( setitimer ( which , & new , & old ) ! = 0 ) {
PyErr_SetFromErrno ( ItimerE rror) ;
PyErr_SetFromErrno ( modstate - > itimer_e rror) ;
return NULL ;
}
return itimer_retval ( & old ) ;
}
# endif
# endif / / HAVE_SETITIMER
# ifdef HAVE_GETITIMER
/*[clinic input]
signal . getitimer
@ -890,17 +917,18 @@ static PyObject *
signal_getitimer_impl ( PyObject * module , int which )
/*[clinic end generated code: output=9e053175d517db40 input=f7d21d38f3490627]*/
{
struct itimerval old ;
_signal_module_state * modstate = get_signal_state ( module ) ;
struct itimerval old ;
if ( getitimer ( which , & old ) ! = 0 ) {
PyErr_SetFromErrno ( ItimerE rror) ;
PyErr_SetFromErrno ( modstate - > itimer_e rror) ;
return NULL ;
}
return itimer_retval ( & old ) ;
}
# endif / / HAVE_GETITIMER
# endif
# if defined(PYPTHREAD_SIGMASK) || defined(HAVE_SIGPENDING)
static PyObject *
@ -1544,17 +1572,17 @@ signal_add_constants(PyObject *module)
static int
signal_get_set_handlers ( PyObject * mod_dict )
signal_get_set_handlers ( signal_state_t * state , PyObject * mod_dict )
{
/ / Get signal handlers
for ( int signum = 1 ; signum < NSIG ; signum + + ) {
void ( * c_handler ) ( int ) = PyOS_getsig ( signum ) ;
PyObject * func ;
if ( c_handler = = SIG_DFL ) {
func = DefaultH andler;
func = state - > default_h andler;
}
else if ( c_handler = = SIG_IGN ) {
func = IgnoreH andler;
func = state - > ignore_h andler;
}
else {
func = Py_None ; / / None of our business
@ -1562,20 +1590,20 @@ signal_get_set_handlers(PyObject *mod_dict)
/ / If signal_module_exec ( ) is called more than one , we must
/ / clear the strong reference to the previous function .
PyObject * old_func = get_handler ( signum ) ;
SetH andler( signum , Py_NewRef ( func ) ) ;
set_h andler( signum , Py_NewRef ( func ) ) ;
Py_XDECREF ( old_func ) ;
}
/ / Instal Python SIGINT handler which raises KeyboardInterrupt
PyObject * sigint_func = get_handler ( SIGINT ) ;
if ( sigint_func = = DefaultH andler) {
if ( sigint_func = = state - > default_h andler) {
PyObject * int_handler = PyMapping_GetItemString ( mod_dict ,
" default_int_handler " ) ;
if ( ! int_handler ) {
return - 1 ;
}
SetH andler( SIGINT , int_handler ) ;
set_h andler( SIGINT , int_handler ) ;
Py_DECREF ( sigint_func ) ;
PyOS_setsig ( SIGINT , signal_handler ) ;
}
@ -1588,20 +1616,34 @@ signal_module_exec(PyObject *m)
{
assert ( ! PyErr_Occurred ( ) ) ;
signal_state_t * state = & signal_global_state ;
_signal_module_state * modstate = get_signal_state ( m ) ;
modstate - > default_handler = state - > default_handler ; / / borrowed ref
modstate - > ignore_handler = state - > ignore_handler ; / / borrowed ref
# ifdef PYHAVE_ITIMER_ERROR
modstate - > itimer_error = PyErr_NewException ( " signal.itimer_error " ,
PyExc_OSError , NULL ) ;
if ( modstate - > itimer_error = = NULL ) {
return - 1 ;
}
# endif
if ( signal_add_constants ( m ) < 0 ) {
return - 1 ;
}
/* Add some symbolic constants to the module */
PyObject * d = PyModule_GetDict ( m ) ;
if ( PyDict_SetItemString ( d , " SIG_DFL " , DefaultHandler ) < 0 ) {
if ( PyDict_SetItemString ( d , " SIG_DFL " , state - > default_h andler) < 0 ) {
return - 1 ;
}
if ( PyDict_SetItemString ( d , " SIG_IGN " , IgnoreHandler ) < 0 ) {
if ( PyDict_SetItemString ( d , " SIG_IGN " , state - > ignore_h andler) < 0 ) {
return - 1 ;
}
# if defined(HAVE_GETITIMER) || defined(HAVE_SETITIMER)
if ( PyDict_SetItemString ( d , " ItimerError " , ItimerError ) < 0 ) {
# ifdef PYHAVE_ITIMER_ERROR
if ( PyDict_SetItemString ( d , " ItimerError " , modstate - > itimer_e rror) < 0 ) {
return - 1 ;
}
# endif
@ -1613,7 +1655,7 @@ signal_module_exec(PyObject *m)
PyThreadState * tstate = _PyThreadState_GET ( ) ;
if ( _Py_IsMainInterpreter ( tstate - > interp ) ) {
if ( signal_get_set_handlers ( d ) < 0 ) {
if ( signal_get_set_handlers ( state , d ) < 0 ) {
return - 1 ;
}
}
@ -1623,6 +1665,31 @@ signal_module_exec(PyObject *m)
}
# ifdef PYHAVE_ITIMER_ERROR
static int
_signal_module_traverse ( PyObject * module , visitproc visit , void * arg )
{
_signal_module_state * modstate = get_signal_state ( module ) ;
Py_VISIT ( modstate - > itimer_error ) ;
return 0 ;
}
static int
_signal_module_clear ( PyObject * module )
{
_signal_module_state * modstate = get_signal_state ( module ) ;
Py_CLEAR ( modstate - > itimer_error ) ;
return 0 ;
}
static void
_signal_module_free ( void * module )
{
_signal_module_clear ( ( PyObject * ) module ) ;
}
# endif / / PYHAVE_ITIMER_ERROR
static PyModuleDef_Slot signal_slots [ ] = {
{ Py_mod_exec , signal_module_exec } ,
{ 0 , NULL }
@ -1632,9 +1699,14 @@ static struct PyModuleDef signal_module = {
PyModuleDef_HEAD_INIT ,
" _signal " ,
. m_doc = module_doc ,
. m_size = 0 ,
. m_size = sizeof ( _signal_module_state ) ,
. m_methods = signal_methods ,
. m_slots = signal_slots ,
# ifdef PYHAVE_ITIMER_ERROR
. m_traverse = _signal_module_traverse ,
. m_clear = _signal_module_clear ,
. m_free = _signal_module_free ,
# endif
} ;
@ -1648,15 +1720,17 @@ PyInit__signal(void)
void
_PySignal_Fini ( void )
{
signal_state_t * state = & signal_global_state ;
/ / Restore default signals and clear handlers
for ( int signum = 1 ; signum < NSIG ; signum + + ) {
PyObject * func = get_handler ( signum ) ;
_Py_atomic_store_relaxed ( & Handlers [ signum ] . tripped , 0 ) ;
SetH andler( signum , NULL ) ;
set_h andler( signum , NULL ) ;
if ( func ! = NULL
& & func ! = Py_None
& & func ! = DefaultH andler
& & func ! = IgnoreH andler)
& & func ! = state - > default_h andler
& & func ! = state - > ignore_h andler)
{
PyOS_setsig ( signum , SIG_DFL ) ;
}
@ -1664,17 +1738,14 @@ _PySignal_Fini(void)
}
# ifdef MS_WINDOWS
if ( sigint_event ! = NULL ) {
CloseHandle ( sigint_event ) ;
sigint_event = NULL ;
if ( state - > s igint_event ! = NULL ) {
CloseHandle ( state - > s igint_event ) ;
state - > s igint_event = NULL ;
}
# endif
Py_CLEAR ( DefaultHandler ) ;
Py_CLEAR ( IgnoreHandler ) ;
# if defined(HAVE_GETITIMER) || defined(HAVE_SETITIMER)
Py_CLEAR ( ItimerError ) ;
# endif
Py_CLEAR ( state - > default_handler ) ;
Py_CLEAR ( state - > ignore_handler ) ;
}
@ -1720,6 +1791,7 @@ _PyErr_CheckSignalsTstate(PyThreadState *tstate)
frame = Py_None ;
}
signal_state_t * state = & signal_global_state ;
for ( int i = 1 ; i < NSIG ; i + + ) {
if ( ! _Py_atomic_load_relaxed ( & Handlers [ i ] . tripped ) ) {
continue ;
@ -1733,8 +1805,8 @@ _PyErr_CheckSignalsTstate(PyThreadState *tstate)
* ( see bpo - 43406 ) .
*/
PyObject * func = get_handler ( i ) ;
if ( func = = NULL | | func = = Py_None | | func = = IgnoreH andler | |
func = = DefaultH andler) {
if ( func = = NULL | | func = = Py_None | | func = = state - > ignore_h andler | |
func = = state - > default_h andler) {
/* No Python signal handler due to aforementioned race condition.
* We can ' t call raise ( ) as it would break the assumption
* that PyErr_SetInterrupt ( ) only * simulates * an incoming
@ -1791,8 +1863,10 @@ PyErr_SetInterruptEx(int signum)
if ( signum < 1 | | signum > = NSIG ) {
return - 1 ;
}
PyObject * func = get_handler ( signum ) ;
if ( func ! = IgnoreHandler & & func ! = DefaultHandler ) {
signal_state_t * state = & signal_global_state ;
PyObject * func = get_handler ( signum ) ;
if ( func ! = state - > ignore_handler & & func ! = state - > default_handler ) {
trip_signal ( signum ) ;
}
return 0 ;
@ -1854,28 +1928,22 @@ _Py_RestoreSignals(void)
int
_PySignal_Init ( int install_signal_handlers )
{
DefaultHandler = PyLong_FromVoidPtr ( ( void * ) SIG_DFL ) ;
if ( ! DefaultHandler ) {
return - 1 ;
}
signal_state_t * state = & signal_global_state ;
IgnoreH andler = PyLong_FromVoidPtr ( ( void * ) SIG_IGN ) ;
if ( ! IgnoreHandler ) {
state - > default_handler = PyLong_FromVoidPtr ( ( void * ) SIG_DFL ) ;
if ( state - > default_handler = = NULL ) {
return - 1 ;
}
# if defined(HAVE_GETITIMER) || defined(HAVE_SETITIMER)
ItimerError = PyErr_NewException ( " signal.ItimerError " ,
PyExc_OSError , NULL ) ;
if ( ! ItimerError ) {
state - > ignore_handler = PyLong_FromVoidPtr ( ( void * ) SIG_IGN ) ;
if ( state - > ignore_handler = = NULL ) {
return - 1 ;
}
# endif
# ifdef MS_WINDOWS
/* Create manual-reset event, initially unset */
sigint_event = CreateEvent ( NULL , TRUE , FALSE , FALSE ) ;
if ( sigint_event = = NULL ) {
state - > s igint_event = CreateEvent ( NULL , TRUE , FALSE , FALSE ) ;
if ( state - > s igint_event = = NULL ) {
PyErr_SetFromWindowsErr ( 0 ) ;
return - 1 ;
}
@ -1963,13 +2031,14 @@ _PyOS_IsMainThread(void)
}
# ifdef MS_WINDOWS
/* Returns a manual-reset event which gets tripped whenever
SIGINT is received .
Python . h does not include windows . h so we do cannot use HANDLE
as the return type of this function . We use void * instead . */
void * _PyOS_SigintEvent ( void )
{
/* Returns a manual-reset event which gets tripped whenever
SIGINT is received .
Python . h does not include windows . h so we do cannot use HANDLE
as the return type of this function . We use void * instead . */
return sigint_event ;
signal_state_t * state = & signal_global_state ;
return state - > sigint_event ;
}
# endif