mirror of
https://github.com/python/cpython.git
synced 2025-07-24 11:44:31 +00:00
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.
This commit is contained in:
parent
a3f19c3f52
commit
d54cfb160c
5 changed files with 142 additions and 105 deletions
|
@ -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)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue