mirror of
https://github.com/python/cpython.git
synced 2025-08-03 16:39:00 +00:00
Issue #12303: Add sigwaitinfo() and sigtimedwait() to the signal module.
This commit is contained in:
parent
bb66972c0b
commit
bc808224b6
8 changed files with 295 additions and 23 deletions
|
@ -507,7 +507,8 @@ PyDoc_STRVAR(getitimer_doc,
|
|||
Returns current value of given itimer.");
|
||||
#endif
|
||||
|
||||
#if defined(PYPTHREAD_SIGMASK) || defined(HAVE_SIGWAIT)
|
||||
#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. */
|
||||
|
||||
|
@ -679,6 +680,140 @@ PyDoc_STRVAR(signal_sigwait_doc,
|
|||
Wait a signal.");
|
||||
#endif /* #ifdef HAVE_SIGPENDING */
|
||||
|
||||
#if defined(HAVE_SIGWAITINFO) || defined(HAVE_SIGTIMEDWAIT)
|
||||
static int initialized;
|
||||
static PyStructSequence_Field struct_siginfo_fields[] = {
|
||||
{"si_signo", "signal number"},
|
||||
{"si_code", "signal code"},
|
||||
{"si_errno", "errno associated with this signal"},
|
||||
{"si_pid", "sending process ID"},
|
||||
{"si_uid", "real user ID of sending process"},
|
||||
{"si_status", "exit value or signal"},
|
||||
{"si_band", "band event for SIGPOLL"},
|
||||
{0}
|
||||
};
|
||||
|
||||
PyDoc_STRVAR(struct_siginfo__doc__,
|
||||
"struct_siginfo: Result from sigwaitinfo or sigtimedwait.\n\n\
|
||||
This object may be accessed either as a tuple of\n\
|
||||
(si_signo, si_code, si_errno, si_pid, si_uid, si_status, si_band),\n\
|
||||
or via the attributes si_signo, si_code, and so on.");
|
||||
|
||||
static PyStructSequence_Desc struct_siginfo_desc = {
|
||||
"signal.struct_siginfo", /* name */
|
||||
struct_siginfo__doc__, /* doc */
|
||||
struct_siginfo_fields, /* fields */
|
||||
7 /* n_in_sequence */
|
||||
};
|
||||
|
||||
static PyTypeObject SiginfoType;
|
||||
|
||||
static PyObject *
|
||||
fill_siginfo(siginfo_t *si)
|
||||
{
|
||||
PyObject *result = PyStructSequence_New(&SiginfoType);
|
||||
if (!result)
|
||||
return NULL;
|
||||
|
||||
PyStructSequence_SET_ITEM(result, 0, PyLong_FromLong((long)(si->si_signo)));
|
||||
PyStructSequence_SET_ITEM(result, 1, PyLong_FromLong((long)(si->si_code)));
|
||||
PyStructSequence_SET_ITEM(result, 2, PyLong_FromLong((long)(si->si_errno)));
|
||||
PyStructSequence_SET_ITEM(result, 3, PyLong_FromPid(si->si_pid));
|
||||
PyStructSequence_SET_ITEM(result, 4, PyLong_FromLong((long)(si->si_uid)));
|
||||
PyStructSequence_SET_ITEM(result, 5,
|
||||
PyLong_FromLong((long)(si->si_status)));
|
||||
PyStructSequence_SET_ITEM(result, 6, PyLong_FromLong(si->si_band));
|
||||
if (PyErr_Occurred()) {
|
||||
Py_DECREF(result);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SIGWAITINFO
|
||||
static PyObject *
|
||||
signal_sigwaitinfo(PyObject *self, PyObject *args)
|
||||
{
|
||||
PyObject *signals;
|
||||
sigset_t set;
|
||||
siginfo_t si;
|
||||
int err;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "O:sigwaitinfo", &signals))
|
||||
return NULL;
|
||||
|
||||
if (iterable_to_sigset(signals, &set))
|
||||
return NULL;
|
||||
|
||||
Py_BEGIN_ALLOW_THREADS
|
||||
err = sigwaitinfo(&set, &si);
|
||||
Py_END_ALLOW_THREADS
|
||||
if (err == -1)
|
||||
return PyErr_SetFromErrno(PyExc_OSError);
|
||||
|
||||
return fill_siginfo(&si);
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(signal_sigwaitinfo_doc,
|
||||
"sigwaitinfo(sigset) -> struct_siginfo\n\
|
||||
\n\
|
||||
Wait synchronously for a signal until one of the signals in *sigset* is\n\
|
||||
delivered.\n\
|
||||
Returns a struct_siginfo containing information about the signal.");
|
||||
#endif /* #ifdef HAVE_SIGWAITINFO */
|
||||
|
||||
#ifdef HAVE_SIGTIMEDWAIT
|
||||
static PyObject *
|
||||
signal_sigtimedwait(PyObject *self, PyObject *args)
|
||||
{
|
||||
PyObject *signals, *timeout;
|
||||
struct timespec buf;
|
||||
sigset_t set;
|
||||
siginfo_t si;
|
||||
int err;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "OO:sigtimedwait", &signals, &timeout))
|
||||
return NULL;
|
||||
|
||||
if (!PyTuple_Check(timeout) || PyTuple_Size(timeout) != 2) {
|
||||
PyErr_SetString(PyExc_TypeError,
|
||||
"sigtimedwait() arg 2 must be a tuple "
|
||||
"(timeout_sec, timeout_nsec)");
|
||||
return NULL;
|
||||
} else if (!PyArg_ParseTuple(timeout, "ll:sigtimedwait",
|
||||
&(buf.tv_sec), &(buf.tv_nsec)))
|
||||
return NULL;
|
||||
|
||||
if (buf.tv_sec < 0 || buf.tv_nsec < 0) {
|
||||
PyErr_SetString(PyExc_ValueError, "timeout must be non-negative");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (iterable_to_sigset(signals, &set))
|
||||
return NULL;
|
||||
|
||||
Py_BEGIN_ALLOW_THREADS
|
||||
err = sigtimedwait(&set, &si, &buf);
|
||||
Py_END_ALLOW_THREADS
|
||||
if (err == -1) {
|
||||
if (errno == EAGAIN)
|
||||
Py_RETURN_NONE;
|
||||
else
|
||||
return PyErr_SetFromErrno(PyExc_OSError);
|
||||
}
|
||||
|
||||
return fill_siginfo(&si);
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(signal_sigtimedwait_doc,
|
||||
"sigtimedwait(sigset, (timeout_sec, timeout_nsec)) -> struct_siginfo\n\
|
||||
\n\
|
||||
Like sigwaitinfo(), but with a timeout specified as a tuple of (seconds,\n\
|
||||
nanoseconds).");
|
||||
#endif /* #ifdef HAVE_SIGTIMEDWAIT */
|
||||
|
||||
|
||||
#if defined(HAVE_PTHREAD_KILL) && defined(WITH_THREAD)
|
||||
static PyObject *
|
||||
|
@ -751,6 +886,14 @@ static PyMethodDef signal_methods[] = {
|
|||
#ifdef HAVE_SIGWAIT
|
||||
{"sigwait", (PyCFunction)signal_sigwait,
|
||||
METH_VARARGS, signal_sigwait_doc},
|
||||
#endif
|
||||
#ifdef HAVE_SIGWAITINFO
|
||||
{"sigwaitinfo", (PyCFunction)signal_sigwaitinfo,
|
||||
METH_VARARGS, signal_sigwaitinfo_doc},
|
||||
#endif
|
||||
#ifdef HAVE_SIGTIMEDWAIT
|
||||
{"sigtimedwait", (PyCFunction)signal_sigtimedwait,
|
||||
METH_VARARGS, signal_sigtimedwait_doc},
|
||||
#endif
|
||||
{NULL, NULL} /* sentinel */
|
||||
};
|
||||
|
@ -820,6 +963,15 @@ PyInit_signal(void)
|
|||
if (m == NULL)
|
||||
return NULL;
|
||||
|
||||
#if defined(HAVE_SIGWAITINFO) || defined(HAVE_SIGTIMEDWAIT)
|
||||
if (!initialized)
|
||||
PyStructSequence_InitType(&SiginfoType, &struct_siginfo_desc);
|
||||
|
||||
Py_INCREF((PyObject*) &SiginfoType);
|
||||
PyModule_AddObject(m, "struct_siginfo", (PyObject*) &SiginfoType);
|
||||
initialized = 1;
|
||||
#endif
|
||||
|
||||
/* Add some symbolic constants to the module */
|
||||
d = PyModule_GetDict(m);
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue