#include "pycore_pyhash.h" // struct pyhash_runtime_state
#include "pycore_pythread.h" // struct _pythread_runtime_state
#include "pycore_obmalloc.h" // struct obmalloc_state
+#include "pycore_signal.h" // struct _signals_runtime_state
#include "pycore_time.h" // struct _time_runtime_state
#include "pycore_tracemalloc.h" // struct _tracemalloc_runtime_state
#include "pycore_unicodeobject.h" // struct _Py_unicode_runtime_ids
struct _pymem_allocators allocators;
struct _obmalloc_state obmalloc;
struct pyhash_runtime_state pyhash_state;
- struct {
- /* True if the main interpreter thread exited due to an unhandled
- * KeyboardInterrupt exception, suggesting the user pressed ^C. */
- int unhandled_keyboard_interrupt;
- } signals;
struct _time_runtime_state time;
struct _pythread_runtime_state threads;
+ struct _signals_runtime_state signals;
struct pyinterpreters {
PyThread_type_lock mutex;
# error "this header requires Py_BUILD_CORE define"
#endif
+#include "pycore_atomic.h" // _Py_atomic_address
+
#include <signal.h> // NSIG
+
#ifdef _SIG_MAXSIG
// gh-91145: On FreeBSD, <signal.h> defines NSIG as 32: it doesn't include
// realtime signals: [SIGRTMIN,SIGRTMAX]. Use _SIG_MAXSIG instead. For
# define Py_NSIG 64 // Use a reasonable default value
#endif
+#define INVALID_FD (-1)
+
+struct _signals_runtime_state {
+ volatile struct {
+ _Py_atomic_int tripped;
+ /* func is atomic to ensure that PyErr_SetInterrupt is async-signal-safe
+ * (even though it would probably be otherwise, anyway).
+ */
+ _Py_atomic_address func;
+ } handlers[Py_NSIG];
+
+ volatile struct {
+#ifdef MS_WINDOWS
+ /* This would be "SOCKET fd" if <winsock2.h> were always included.
+ It isn't so we must cast to SOCKET where appropriate. */
+ volatile int fd;
+#elif defined(__VXWORKS__)
+ int fd;
+#else
+ sig_atomic_t fd;
+#endif
+
+ int warn_on_full_buffer;
+#ifdef MS_WINDOWS
+ int use_send;
+#endif
+ } wakeup;
+
+ /* Speed up sigcheck() when none tripped */
+ _Py_atomic_int is_tripped;
+
+ /* These objects necessarily belong to the main interpreter. */
+ PyObject *default_handler;
+ PyObject *ignore_handler;
+
+#ifdef MS_WINDOWS
+ /* This would be "HANDLE sigint_event" if <windows.h> were always included.
+ It isn't so we must cast to HANDLE everywhere "sigint_event" is used. */
+ void *sigint_event;
+#endif
+
+ /* True if the main interpreter thread exited due to an unhandled
+ * KeyboardInterrupt exception, suggesting the user pressed ^C. */
+ int unhandled_keyboard_interrupt;
+};
+
+#ifdef MS_WINDOWS
+# define _signals_WAKEUP_INIT \
+ {.fd = INVALID_FD, .warn_on_full_buffer = 1, .use_send = 0}
+#else
+# define _signals_WAKEUP_INIT \
+ {.fd = INVALID_FD, .warn_on_full_buffer = 1}
+#endif
+
+#define _signals_RUNTIME_INIT \
+ { \
+ .wakeup = _signals_WAKEUP_INIT, \
+ }
+
+
#ifdef __cplusplus
}
#endif
#include "pycore_moduleobject.h" // _PyModule_GetState()
#include "pycore_pyerrors.h" // _PyErr_SetString()
#include "pycore_pystate.h" // _PyThreadState_GET()
-#include "pycore_signal.h" // Py_NSIG
+#include "pycore_signal.h"
#ifndef MS_WINDOWS
# include "posixmodule.h"
#endif
#ifdef MS_WINDOWS
-# include <windows.h>
# ifdef HAVE_PROCESS_H
# include <process.h>
# endif
#endif
+#include "pycore_signal.h" // Py_NSIG
+
#ifdef HAVE_SIGNAL_H
# include <signal.h>
#endif
may not be the thread that received the signal.
*/
-static volatile struct {
- _Py_atomic_int tripped;
- /* func is atomic to ensure that PyErr_SetInterrupt is async-signal-safe
- * (even though it would probably be otherwise, anyway).
- */
- _Py_atomic_address func;
-} Handlers[Py_NSIG];
-
-#ifdef MS_WINDOWS
-#define INVALID_FD ((SOCKET_T)-1)
-
-static volatile struct {
- SOCKET_T fd;
- int warn_on_full_buffer;
- int use_send;
-} wakeup = {.fd = INVALID_FD, .warn_on_full_buffer = 1, .use_send = 0};
-#else
-#define INVALID_FD (-1)
-static volatile struct {
-#ifdef __VXWORKS__
- int fd;
-#else
- sig_atomic_t fd;
-#endif
- int warn_on_full_buffer;
-} wakeup = {.fd = INVALID_FD, .warn_on_full_buffer = 1};
-#endif
-
-/* Speed up sigcheck() when none tripped */
-static _Py_atomic_int is_tripped;
-
-typedef struct {
- PyObject *default_handler;
- PyObject *ignore_handler;
-#ifdef MS_WINDOWS
- HANDLE sigint_event;
-#endif
-} signal_state_t;
+#define Handlers _PyRuntime.signals.handlers
+#define wakeup _PyRuntime.signals.wakeup
+#define is_tripped _PyRuntime.signals.is_tripped
// State shared by all Python interpreters
-static signal_state_t signal_global_state = {0};
+typedef struct _signals_runtime_state signal_state_t;
+#define signal_global_state _PyRuntime.signals
#if defined(HAVE_GETITIMER) || defined(HAVE_SETITIMER)
# define PYHAVE_ITIMER_ERROR
See bpo-30038 for more details.
*/
- int fd;
-#ifdef MS_WINDOWS
- fd = Py_SAFE_DOWNCAST(wakeup.fd, SOCKET_T, int);
-#else
- fd = wakeup.fd;
-#endif
-
+ int fd = wakeup.fd;
if (fd != INVALID_FD) {
unsigned char byte = (unsigned char)sig_num;
#ifdef MS_WINDOWS
#ifdef MS_WINDOWS
if (sig_num == SIGINT) {
signal_state_t *state = &signal_global_state;
- SetEvent(state->sigint_event);
+ SetEvent((HANDLE)state->sigint_event);
}
#endif
}
}
old_sockfd = wakeup.fd;
- wakeup.fd = sockfd;
+ wakeup.fd = Py_SAFE_DOWNCAST(sockfd, SOCKET_T, int);
wakeup.warn_on_full_buffer = warn_on_full_buffer;
wakeup.use_send = is_socket;
fd = -1;
}
-#ifdef MS_WINDOWS
- int old_fd = Py_SAFE_DOWNCAST(wakeup.fd, SOCKET_T, int);
-#else
int old_fd = wakeup.fd;
-#endif
wakeup.fd = fd;
wakeup.warn_on_full_buffer = 1;
return old_fd;
signal_state_t *state = &signal_global_state;
_signal_module_state *modstate = get_signal_state(m);
+ // XXX For proper isolation, these values must be guaranteed
+ // to be effectively const (e.g. immortal).
modstate->default_handler = state->default_handler; // borrowed ref
modstate->ignore_handler = state->ignore_handler; // borrowed ref
#ifdef MS_WINDOWS
if (state->sigint_event != NULL) {
- CloseHandle(state->sigint_event);
+ CloseHandle((HANDLE)state->sigint_event);
state->sigint_event = NULL;
}
#endif
#ifdef MS_WINDOWS
/* Create manual-reset event, initially unset */
- state->sigint_event = CreateEvent(NULL, TRUE, FALSE, FALSE);
+ state->sigint_event = (void *)CreateEvent(NULL, TRUE, FALSE, FALSE);
if (state->sigint_event == NULL) {
PyErr_SetFromWindowsErr(0);
return -1;