bpo-43356: Allow passing a signal number to interrupt_main() (GH-24755)

Also introduce a new C API ``PyErr_SetInterruptEx(int signum)``.
diff --git a/Include/internal/pycore_pylifecycle.h b/Include/internal/pycore_pylifecycle.h
index a7d84a9..7ae107d 100644
--- a/Include/internal/pycore_pylifecycle.h
+++ b/Include/internal/pycore_pylifecycle.h
@@ -8,8 +8,24 @@ extern "C" {
 #  error "this header requires Py_BUILD_CORE define"
 #endif
 
+#ifdef HAVE_SIGNAL_H
+#include <signal.h>
+#endif
+
 #include "pycore_runtime.h"       // _PyRuntimeState
 
+#ifndef NSIG
+# if defined(_NSIG)
+#  define NSIG _NSIG            /* For BSD/SysV */
+# elif defined(_SIGMAX)
+#  define NSIG (_SIGMAX + 1)    /* For QNX */
+# elif defined(SIGMAX)
+#  define NSIG (SIGMAX + 1)     /* For djgpp */
+# else
+#  define NSIG 64               /* Use a reasonable default value */
+# endif
+#endif
+
 /* Forward declarations */
 struct _PyArgv;
 struct pyruntimestate;
diff --git a/Include/pyerrors.h b/Include/pyerrors.h
index 692d671..14129d3 100644
--- a/Include/pyerrors.h
+++ b/Include/pyerrors.h
@@ -224,6 +224,9 @@ PyAPI_FUNC(void) PyErr_WriteUnraisable(PyObject *);
 /* In signalmodule.c */
 PyAPI_FUNC(int) PyErr_CheckSignals(void);
 PyAPI_FUNC(void) PyErr_SetInterrupt(void);
+#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x030A0000
+PyAPI_FUNC(int) PyErr_SetInterruptEx(int signum);
+#endif
 
 /* Support for adding program text to SyntaxErrors */
 PyAPI_FUNC(void) PyErr_SyntaxLocation(