diff options
author | Antoine Pitrou <pitrou@free.fr> | 2018-05-04 13:00:50 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-05-04 13:00:50 +0200 |
commit | 9d3627e311211a1b4abcda29c36fe4afe2c46532 (patch) | |
tree | 26f76c94bb55ee8b242f044efa26cfd8b08e9d26 /Modules | |
parent | 491bbedc209fea314a04cb3015da68fb0aa63238 (diff) | |
download | cpython-git-9d3627e311211a1b4abcda29c36fe4afe2c46532.tar.gz |
bpo-33332: Add signal.valid_signals() (GH-6581)
Diffstat (limited to 'Modules')
-rw-r--r-- | Modules/clinic/signalmodule.c.h | 31 | ||||
-rw-r--r-- | Modules/signalmodule.c | 64 |
2 files changed, 89 insertions, 6 deletions
diff --git a/Modules/clinic/signalmodule.c.h b/Modules/clinic/signalmodule.c.h index 1c439716c4..eca2da10ad 100644 --- a/Modules/clinic/signalmodule.c.h +++ b/Modules/clinic/signalmodule.c.h @@ -341,6 +341,31 @@ PyDoc_STRVAR(signal_sigwait__doc__, #endif /* defined(HAVE_SIGWAIT) */ +#if (defined(HAVE_SIGFILLSET) || defined(MS_WINDOWS)) + +PyDoc_STRVAR(signal_valid_signals__doc__, +"valid_signals($module, /)\n" +"--\n" +"\n" +"Return a set of valid signal numbers on this platform.\n" +"\n" +"The signal numbers returned by this function can be safely passed to\n" +"functions like `pthread_sigmask`."); + +#define SIGNAL_VALID_SIGNALS_METHODDEF \ + {"valid_signals", (PyCFunction)signal_valid_signals, METH_NOARGS, signal_valid_signals__doc__}, + +static PyObject * +signal_valid_signals_impl(PyObject *module); + +static PyObject * +signal_valid_signals(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return signal_valid_signals_impl(module); +} + +#endif /* (defined(HAVE_SIGFILLSET) || defined(MS_WINDOWS)) */ + #if defined(HAVE_SIGWAITINFO) PyDoc_STRVAR(signal_sigwaitinfo__doc__, @@ -459,6 +484,10 @@ exit: #define SIGNAL_SIGWAIT_METHODDEF #endif /* !defined(SIGNAL_SIGWAIT_METHODDEF) */ +#ifndef SIGNAL_VALID_SIGNALS_METHODDEF + #define SIGNAL_VALID_SIGNALS_METHODDEF +#endif /* !defined(SIGNAL_VALID_SIGNALS_METHODDEF) */ + #ifndef SIGNAL_SIGWAITINFO_METHODDEF #define SIGNAL_SIGWAITINFO_METHODDEF #endif /* !defined(SIGNAL_SIGWAITINFO_METHODDEF) */ @@ -470,4 +499,4 @@ exit: #ifndef SIGNAL_PTHREAD_KILL_METHODDEF #define SIGNAL_PTHREAD_KILL_METHODDEF #endif /* !defined(SIGNAL_PTHREAD_KILL_METHODDEF) */ -/*[clinic end generated code: output=7b41486acf93aa8e input=a9049054013a1b77]*/ +/*[clinic end generated code: output=f35d79e0cfee3f1b input=a9049054013a1b77]*/ diff --git a/Modules/signalmodule.c b/Modules/signalmodule.c index 35fd87e2d1..003bbb60e3 100644 --- a/Modules/signalmodule.c +++ b/Modules/signalmodule.c @@ -841,11 +841,21 @@ iterable_to_sigset(PyObject *iterable, sigset_t *mask) if (signum == -1 && PyErr_Occurred()) goto error; if (0 < signum && signum < NSIG) { - /* bpo-33329: ignore sigaddset() return value as it can fail - * for some reserved signals, but we want the `range(1, NSIG)` - * idiom to allow selecting all valid signals. - */ - (void) sigaddset(mask, (int)signum); + if (sigaddset(mask, (int)signum)) { + if (errno != EINVAL) { + /* Probably impossible */ + PyErr_SetFromErrno(PyExc_OSError); + goto error; + } + /* For backwards compatibility, allow idioms such as + * `range(1, NSIG)` but warn about invalid signal numbers + */ + const char *msg = + "invalid signal number %ld, please use valid_signals()"; + if (PyErr_WarnFormat(PyExc_RuntimeWarning, 1, msg, signum)) { + goto error; + } + } } else { PyErr_Format(PyExc_ValueError, @@ -1001,6 +1011,47 @@ signal_sigwait(PyObject *module, PyObject *sigset) #endif /* #ifdef HAVE_SIGWAIT */ +#if defined(HAVE_SIGFILLSET) || defined(MS_WINDOWS) + +/*[clinic input] +signal.valid_signals + +Return a set of valid signal numbers on this platform. + +The signal numbers returned by this function can be safely passed to +functions like `pthread_sigmask`. +[clinic start generated code]*/ + +static PyObject * +signal_valid_signals_impl(PyObject *module) +/*[clinic end generated code: output=1609cffbcfcf1314 input=86a3717ff25288f2]*/ +{ +#ifdef MS_WINDOWS +#ifdef SIGBREAK + PyObject *tup = Py_BuildValue("(iiiiiii)", SIGABRT, SIGBREAK, SIGFPE, + SIGILL, SIGINT, SIGSEGV, SIGTERM); +#else + PyObject *tup = Py_BuildValue("(iiiiii)", SIGABRT, SIGFPE, SIGILL, + SIGINT, SIGSEGV, SIGTERM); +#endif + if (tup == NULL) { + return NULL; + } + PyObject *set = PySet_New(tup); + Py_DECREF(tup); + return set; +#else + sigset_t mask; + if (sigemptyset(&mask) || sigfillset(&mask)) { + return PyErr_SetFromErrno(PyExc_OSError); + } + return sigset_to_set(mask); +#endif +} + +#endif /* #if defined(HAVE_SIGFILLSET) || defined(MS_WINDOWS) */ + + #if defined(HAVE_SIGWAITINFO) || defined(HAVE_SIGTIMEDWAIT) static int initialized; static PyStructSequence_Field struct_siginfo_fields[] = { @@ -1225,6 +1276,9 @@ static PyMethodDef signal_methods[] = { SIGNAL_SIGWAIT_METHODDEF SIGNAL_SIGWAITINFO_METHODDEF SIGNAL_SIGTIMEDWAIT_METHODDEF +#if defined(HAVE_SIGFILLSET) || defined(MS_WINDOWS) + SIGNAL_VALID_SIGNALS_METHODDEF +#endif {NULL, NULL} /* sentinel */ }; |