several python improvements.

- add kore.time() as equivalent for kore_time_ms().
- call waitpid() until no more children are available for reaping otherwise
  we risk missing a process if several die at the same time and only one
  SIGCHLD is delivered to us.
- drain a RECV socket operation if eof is set but no exception was given.
This commit is contained in:
Joris Vink 2018-10-30 20:28:27 +01:00
parent 5456f2e1d5
commit 2dd66586ff
3 changed files with 56 additions and 33 deletions

View File

@ -32,6 +32,7 @@ struct python_coro {
TAILQ_HEAD(coro_list, python_coro);
static PyObject *python_kore_log(PyObject *, PyObject *);
static PyObject *python_kore_time(PyObject *, PyObject *);
static PyObject *python_kore_lock(PyObject *, PyObject *);
static PyObject *python_kore_proc(PyObject *, PyObject *);
static PyObject *python_kore_bind(PyObject *, PyObject *);
@ -59,6 +60,7 @@ static PyObject *python_websocket_broadcast(PyObject *, PyObject *);
static struct PyMethodDef pykore_methods[] = {
METHOD("log", python_kore_log, METH_VARARGS),
METHOD("time", python_kore_time, METH_NOARGS),
METHOD("lock", python_kore_lock, METH_NOARGS),
METHOD("proc", python_kore_proc, METH_VARARGS),
METHOD("bind", python_kore_bind, METH_VARARGS),

View File

@ -1501,6 +1501,10 @@ http_request_new(struct connection *c, const char *host,
req->host = host;
req->path = path;
#if defined(KORE_USE_PYTHON)
req->py_coro = NULL;
#endif
if (qsoff > 0) {
req->query_string = path + qsoff;
*(req->query_string)++ = '\0';

View File

@ -324,33 +324,43 @@ kore_python_proc_reap(void)
pid_t child;
int status;
if ((child = waitpid(-1, &status, 0)) == -1) {
if (errno == ECHILD)
for (;;) {
if ((child = waitpid(-1, &status, WNOHANG)) == -1) {
if (errno == ECHILD)
return;
if (errno == EINTR)
continue;
kore_log(LOG_NOTICE, "waitpid: %s", errno_s);
return;
kore_log(LOG_NOTICE, "waitpid: %s", errno_s);
return;
}
if (child == 0)
return;
proc = NULL;
TAILQ_FOREACH(proc, &procs, list) {
if (proc->pid == child)
break;
}
if (proc == NULL)
continue;
proc->pid = -1;
proc->reaped = 1;
proc->status = status;
if (proc->timer != NULL) {
kore_timer_remove(proc->timer);
proc->timer = NULL;
}
if (proc->coro->request != NULL)
http_request_wakeup(proc->coro->request);
else
python_coro_wakeup(proc->coro);
}
proc = NULL;
TAILQ_FOREACH(proc, &procs, list) {
if (proc->pid == child)
break;
}
if (proc == NULL) {
kore_log(LOG_NOTICE, "SIGCHLD for unknown proc (%d)", child);
return;
}
proc->pid = -1;
proc->reaped = 1;
proc->status = status;
if (proc->coro->request != NULL)
http_request_wakeup(proc->coro->request);
else
python_coro_wakeup(proc->coro);
}
static void *
@ -880,6 +890,16 @@ python_kore_log(PyObject *self, PyObject *args)
Py_RETURN_TRUE;
}
static PyObject *
python_kore_time(PyObject *self, PyObject *args)
{
u_int64_t now;
now = kore_time_ms();
return (PyLong_FromUnsignedLongLong(now));
}
static PyObject *
python_kore_bind(PyObject *self, PyObject *args)
{
@ -1238,11 +1258,8 @@ python_kore_proc(PyObject *self, PyObject *args)
close(out_pipe[1]);
if (!kore_connection_nonblock(in_pipe[1], 0) ||
!kore_connection_nonblock(out_pipe[0], 0)) {
Py_DECREF((PyObject *)proc);
PyErr_SetString(PyExc_RuntimeError, errno_s);
return (NULL);
}
!kore_connection_nonblock(out_pipe[0], 0))
fatal("failed to mark kore.proc pipes are non-blocking");
proc->in->fd = in_pipe[1];
proc->out->fd = out_pipe[0];
@ -1705,9 +1722,9 @@ pysocket_op_iternext(struct pysocket_op *op)
return (NULL);
}
PyErr_SetNone(PyExc_StopIteration);
return (NULL);
/* Drain the recv socket. */
op->data.evt.flags |= KORE_EVENT_READ;
return (pysocket_async_recv(op));
}
switch (op->data.type) {