diff options
author | 2018-05-08 07:48:50 +0300 | |
---|---|---|
committer | 2018-05-08 07:48:50 +0300 | |
commit | d54cfb160c626626394e2f171d3ccfe03309f34e (patch) | |
tree | 7cadfc0541bd650485f4e8e1e9ee45252492f06e /Modules | |
parent | Remove mojibake in the locale aliases mapping. (GH-6716) (diff) | |
download | cpython-d54cfb160c626626394e2f171d3ccfe03309f34e.tar.gz cpython-d54cfb160c626626394e2f171d3ccfe03309f34e.tar.bz2 cpython-d54cfb160c626626394e2f171d3ccfe03309f34e.zip |
bpo-33441: Make the sigset_t converter available in other modules. (GH-6720)
* Expose the sigset_t converter via private API _Py_Sigset_Converter().
* Use Argument Clinic for parsing sigset_t in signalmodule.c.
* Raise ValueError instead OverflowError for integers out of
the C long range.
Based on patch by Pablo Galindo Salgado.
Diffstat (limited to 'Modules')
-rw-r--r-- | Modules/clinic/signalmodule.c.h | 55 | ||||
-rw-r--r-- | Modules/posixmodule.c | 59 | ||||
-rw-r--r-- | Modules/posixmodule.h | 9 | ||||
-rw-r--r-- | Modules/signalmodule.c | 120 |
4 files changed, 138 insertions, 105 deletions
diff --git a/Modules/clinic/signalmodule.c.h b/Modules/clinic/signalmodule.c.h index eca2da10ad3..4d7ac38372f 100644 --- a/Modules/clinic/signalmodule.c.h +++ b/Modules/clinic/signalmodule.c.h @@ -278,17 +278,17 @@ PyDoc_STRVAR(signal_pthread_sigmask__doc__, {"pthread_sigmask", (PyCFunction)signal_pthread_sigmask, METH_FASTCALL, signal_pthread_sigmask__doc__}, static PyObject * -signal_pthread_sigmask_impl(PyObject *module, int how, PyObject *mask); +signal_pthread_sigmask_impl(PyObject *module, int how, sigset_t mask); static PyObject * signal_pthread_sigmask(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; int how; - PyObject *mask; + sigset_t mask; - if (!_PyArg_ParseStack(args, nargs, "iO:pthread_sigmask", - &how, &mask)) { + if (!_PyArg_ParseStack(args, nargs, "iO&:pthread_sigmask", + &how, _Py_Sigset_Converter, &mask)) { goto exit; } return_value = signal_pthread_sigmask_impl(module, how, mask); @@ -339,6 +339,24 @@ PyDoc_STRVAR(signal_sigwait__doc__, #define SIGNAL_SIGWAIT_METHODDEF \ {"sigwait", (PyCFunction)signal_sigwait, METH_O, signal_sigwait__doc__}, +static PyObject * +signal_sigwait_impl(PyObject *module, sigset_t sigset); + +static PyObject * +signal_sigwait(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + sigset_t sigset; + + if (!PyArg_Parse(arg, "O&:sigwait", _Py_Sigset_Converter, &sigset)) { + goto exit; + } + return_value = signal_sigwait_impl(module, sigset); + +exit: + return return_value; +} + #endif /* defined(HAVE_SIGWAIT) */ #if (defined(HAVE_SIGFILLSET) || defined(MS_WINDOWS)) @@ -379,6 +397,24 @@ PyDoc_STRVAR(signal_sigwaitinfo__doc__, #define SIGNAL_SIGWAITINFO_METHODDEF \ {"sigwaitinfo", (PyCFunction)signal_sigwaitinfo, METH_O, signal_sigwaitinfo__doc__}, +static PyObject * +signal_sigwaitinfo_impl(PyObject *module, sigset_t sigset); + +static PyObject * +signal_sigwaitinfo(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + sigset_t sigset; + + if (!PyArg_Parse(arg, "O&:sigwaitinfo", _Py_Sigset_Converter, &sigset)) { + goto exit; + } + return_value = signal_sigwaitinfo_impl(module, sigset); + +exit: + return return_value; +} + #endif /* defined(HAVE_SIGWAITINFO) */ #if defined(HAVE_SIGTIMEDWAIT) @@ -395,19 +431,18 @@ PyDoc_STRVAR(signal_sigtimedwait__doc__, {"sigtimedwait", (PyCFunction)signal_sigtimedwait, METH_FASTCALL, signal_sigtimedwait__doc__}, static PyObject * -signal_sigtimedwait_impl(PyObject *module, PyObject *sigset, +signal_sigtimedwait_impl(PyObject *module, sigset_t sigset, PyObject *timeout_obj); static PyObject * signal_sigtimedwait(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; - PyObject *sigset; + sigset_t sigset; PyObject *timeout_obj; - if (!_PyArg_UnpackStack(args, nargs, "sigtimedwait", - 2, 2, - &sigset, &timeout_obj)) { + if (!_PyArg_ParseStack(args, nargs, "O&O:sigtimedwait", + _Py_Sigset_Converter, &sigset, &timeout_obj)) { goto exit; } return_value = signal_sigtimedwait_impl(module, sigset, timeout_obj); @@ -499,4 +534,4 @@ exit: #ifndef SIGNAL_PTHREAD_KILL_METHODDEF #define SIGNAL_PTHREAD_KILL_METHODDEF #endif /* !defined(SIGNAL_PTHREAD_KILL_METHODDEF) */ -/*[clinic end generated code: output=f35d79e0cfee3f1b input=a9049054013a1b77]*/ +/*[clinic end generated code: output=549f0efdc7405834 input=a9049054013a1b77]*/ diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index 4ac6e765899..a9b3917188c 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -1267,6 +1267,65 @@ PyLong_FromPy_off_t(Py_off_t offset) #endif } +#ifdef HAVE_SIGSET_T +/* Convert an iterable of integers to a sigset. + Return 1 on success, return 0 and raise an exception on error. */ +int +_Py_Sigset_Converter(PyObject *obj, void *addr) +{ + sigset_t *mask = (sigset_t *)addr; + PyObject *iterator, *item; + long signum; + int overflow; + + if (sigemptyset(mask)) { + /* Probably only if mask == NULL. */ + PyErr_SetFromErrno(PyExc_OSError); + return 0; + } + + iterator = PyObject_GetIter(obj); + if (iterator == NULL) { + return 0; + } + + while ((item = PyIter_Next(iterator)) != NULL) { + signum = PyLong_AsLongAndOverflow(item, &overflow); + Py_DECREF(item); + if (signum <= 0 || signum >= NSIG) { + if (overflow || signum != -1 || !PyErr_Occurred()) { + PyErr_Format(PyExc_ValueError, + "signal number %ld out of range", signum); + } + goto error; + } + 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; + } + } + } + if (!PyErr_Occurred()) { + Py_DECREF(iterator); + return 1; + } + +error: + Py_DECREF(iterator); + return 0; +} +#endif /* HAVE_SIGSET_T */ + #ifdef MS_WINDOWS static int diff --git a/Modules/posixmodule.h b/Modules/posixmodule.h index 1ec1833825f..1e00562abc3 100644 --- a/Modules/posixmodule.h +++ b/Modules/posixmodule.h @@ -17,8 +17,17 @@ PyAPI_FUNC(PyObject *) _PyLong_FromGid(gid_t); PyAPI_FUNC(int) _Py_Uid_Converter(PyObject *, void *); PyAPI_FUNC(int) _Py_Gid_Converter(PyObject *, void *); #endif /* MS_WINDOWS */ + +#if defined(PYPTHREAD_SIGMASK) || defined(HAVE_SIGWAIT) || \ + defined(HAVE_SIGWAITINFO) || defined(HAVE_SIGTIMEDWAIT) +# define HAVE_SIGSET_T #endif +#ifdef HAVE_SIGSET_T +PyAPI_FUNC(int) _Py_Sigset_Converter(PyObject *, void *); +#endif /* HAVE_SIGSET_T */ +#endif /* Py_LIMITED_API */ + #ifdef __cplusplus } #endif diff --git a/Modules/signalmodule.c b/Modules/signalmodule.c index 003bbb60e38..818df7d46e4 100644 --- a/Modules/signalmodule.c +++ b/Modules/signalmodule.c @@ -59,6 +59,14 @@ module signal [clinic start generated code]*/ /*[clinic end generated code: output=da39a3ee5e6b4b0d input=b0301a3bde5fe9d3]*/ +/*[python input] + +class sigset_t_converter(CConverter): + type = 'sigset_t' + converter = '_Py_Sigset_Converter' + +[python start generated code]*/ +/*[python end generated code: output=da39a3ee5e6b4b0d input=b5689d14466b6823]*/ /* NOTES ON THE INTERACTION BETWEEN SIGNALS AND THREADS @@ -808,69 +816,6 @@ signal_getitimer_impl(PyObject *module, int which) #endif -#if defined(PYPTHREAD_SIGMASK) || defined(HAVE_SIGWAIT) || \ - defined(HAVE_SIGWAITINFO) || defined(HAVE_SIGTIMEDWAIT) -/* Convert an iterable to a sigset. - Return 0 on success, return -1 and raise an exception on error. */ - -static int -iterable_to_sigset(PyObject *iterable, sigset_t *mask) -{ - int result = -1; - PyObject *iterator, *item; - long signum; - - sigemptyset(mask); - - iterator = PyObject_GetIter(iterable); - if (iterator == NULL) - goto error; - - while (1) - { - item = PyIter_Next(iterator); - if (item == NULL) { - if (PyErr_Occurred()) - goto error; - else - break; - } - - signum = PyLong_AsLong(item); - Py_DECREF(item); - if (signum == -1 && PyErr_Occurred()) - goto error; - if (0 < signum && signum < NSIG) { - 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, - "signal number %ld out of range", signum); - goto error; - } - } - result = 0; - -error: - Py_XDECREF(iterator); - return result; -} -#endif - #if defined(PYPTHREAD_SIGMASK) || defined(HAVE_SIGPENDING) static PyObject* sigset_to_set(sigset_t mask) @@ -913,23 +858,20 @@ sigset_to_set(sigset_t mask) signal.pthread_sigmask how: int - mask: object + mask: sigset_t / Fetch and/or change the signal mask of the calling thread. [clinic start generated code]*/ static PyObject * -signal_pthread_sigmask_impl(PyObject *module, int how, PyObject *mask) -/*[clinic end generated code: output=ff640fe092bc9181 input=f3b7d7a61b7b8283]*/ +signal_pthread_sigmask_impl(PyObject *module, int how, sigset_t mask) +/*[clinic end generated code: output=0562c0fb192981a8 input=85bcebda442fa77f]*/ { - sigset_t newmask, previous; + sigset_t previous; int err; - if (iterable_to_sigset(mask, &newmask)) - return NULL; - - err = pthread_sigmask(how, &newmask, &previous); + err = pthread_sigmask(how, &mask, &previous); if (err != 0) { errno = err; PyErr_SetFromErrno(PyExc_OSError); @@ -977,7 +919,7 @@ signal_sigpending_impl(PyObject *module) /*[clinic input] signal.sigwait - sigset: object + sigset: sigset_t / Wait for a signal. @@ -988,17 +930,13 @@ and returns the signal number. [clinic start generated code]*/ static PyObject * -signal_sigwait(PyObject *module, PyObject *sigset) -/*[clinic end generated code: output=557173647424f6e4 input=11af2d82d83c2e94]*/ +signal_sigwait_impl(PyObject *module, sigset_t sigset) +/*[clinic end generated code: output=f43770699d682f96 input=a6fbd47b1086d119]*/ { - sigset_t set; int err, signum; - if (iterable_to_sigset(sigset, &set)) - return NULL; - Py_BEGIN_ALLOW_THREADS - err = sigwait(&set, &signum); + err = sigwait(&sigset, &signum); Py_END_ALLOW_THREADS if (err) { errno = err; @@ -1113,7 +1051,7 @@ fill_siginfo(siginfo_t *si) /*[clinic input] signal.sigwaitinfo - sigset: object + sigset: sigset_t / Wait synchronously until one of the signals in *sigset* is delivered. @@ -1122,20 +1060,16 @@ Returns a struct_siginfo containing information about the signal. [clinic start generated code]*/ static PyObject * -signal_sigwaitinfo(PyObject *module, PyObject *sigset) -/*[clinic end generated code: output=c40f27b269cd2309 input=f3779a74a991e171]*/ +signal_sigwaitinfo_impl(PyObject *module, sigset_t sigset) +/*[clinic end generated code: output=1eb2f1fa236fdbca input=3d1a7e1f27fc664c]*/ { - sigset_t set; siginfo_t si; int err; int async_err = 0; - if (iterable_to_sigset(sigset, &set)) - return NULL; - do { Py_BEGIN_ALLOW_THREADS - err = sigwaitinfo(&set, &si); + err = sigwaitinfo(&sigset, &si); Py_END_ALLOW_THREADS } while (err == -1 && errno == EINTR && !(async_err = PyErr_CheckSignals())); @@ -1152,7 +1086,7 @@ signal_sigwaitinfo(PyObject *module, PyObject *sigset) /*[clinic input] signal.sigtimedwait - sigset: object + sigset: sigset_t timeout as timeout_obj: object / @@ -1162,12 +1096,11 @@ The timeout is specified in seconds, with floating point numbers allowed. [clinic start generated code]*/ static PyObject * -signal_sigtimedwait_impl(PyObject *module, PyObject *sigset, +signal_sigtimedwait_impl(PyObject *module, sigset_t sigset, PyObject *timeout_obj) -/*[clinic end generated code: output=f7eff31e679f4312 input=53fd4ea3e3724eb8]*/ +/*[clinic end generated code: output=59c8971e8ae18a64 input=87fd39237cf0b7ba]*/ { struct timespec ts; - sigset_t set; siginfo_t si; int res; _PyTime_t timeout, deadline, monotonic; @@ -1181,9 +1114,6 @@ signal_sigtimedwait_impl(PyObject *module, PyObject *sigset, return NULL; } - if (iterable_to_sigset(sigset, &set)) - return NULL; - deadline = _PyTime_GetMonotonicClock() + timeout; do { @@ -1191,7 +1121,7 @@ signal_sigtimedwait_impl(PyObject *module, PyObject *sigset, return NULL; Py_BEGIN_ALLOW_THREADS - res = sigtimedwait(&set, &si, &ts); + res = sigtimedwait(&sigset, &si, &ts); Py_END_ALLOW_THREADS if (res != -1) |