kore

Kore is a web application platform for writing scalable, concurrent web based processes in C or Python.
Commits | Files | Refs | README | LICENSE | git clone https://git.kore.io/kore.git

commit dd93790d80898b5cd40e01c50ad23d8f39546906
parent eab8dcd9ac351a8219af071d1f3280ba4767a85b
Author: Joris Vink <joris@coders.se>
Date:   Wed, 19 Oct 2022 08:04:16 +0200

Improve kore.proc in the Python API.

Allow passing of an env keyword, allowing you to set environment variables
that may be required by the subprocess.

The env keyword must be a list with correctly formed environment variables.

eg:

proc = kore.proc("/bin/myproc",
    env=[
        "LD_LIBRARY_PATH=/my/path"
    ]
)

Diffstat:
include/kore/python_methods.h | 6++++--
src/python.c | 44+++++++++++++++++++++++++++++++++++++++++---
2 files changed, 45 insertions(+), 5 deletions(-)

diff --git a/include/kore/python_methods.h b/include/kore/python_methods.h @@ -39,7 +39,6 @@ static PyObject *python_kore_app(PyObject *, PyObject *); 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_fatal(PyObject *, PyObject *); static PyObject *python_kore_queue(PyObject *, PyObject *); static PyObject *python_kore_worker(PyObject *, PyObject *); @@ -56,6 +55,7 @@ static PyObject *python_kore_task_kill(PyObject *, PyObject *); static PyObject *python_kore_prerequest(PyObject *, PyObject *); static PyObject *python_kore_task_create(PyObject *, PyObject *); static PyObject *python_kore_socket_wrap(PyObject *, PyObject *); +static PyObject *python_kore_proc(PyObject *, PyObject *, PyObject *); static PyObject *python_kore_route(PyObject *, PyObject *, PyObject *); static PyObject *python_kore_timer(PyObject *, PyObject *, PyObject *); static PyObject *python_kore_domain(PyObject *, PyObject *, PyObject *); @@ -92,7 +92,6 @@ 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("queue", python_kore_queue, METH_VARARGS), METHOD("worker", python_kore_worker, METH_VARARGS), METHOD("tracer", python_kore_tracer, METH_VARARGS), @@ -109,6 +108,7 @@ static struct PyMethodDef pykore_methods[] = { METHOD("prerequest", python_kore_prerequest, METH_VARARGS), METHOD("task_create", python_kore_task_create, METH_VARARGS), METHOD("socket_wrap", python_kore_socket_wrap, METH_VARARGS), + METHOD("proc", python_kore_proc, METH_VARARGS | METH_KEYWORDS), METHOD("route", python_kore_route, METH_VARARGS | METH_KEYWORDS), METHOD("timer", python_kore_timer, METH_VARARGS | METH_KEYWORDS), METHOD("domain", python_kore_domain, METH_VARARGS | METH_KEYWORDS), @@ -560,6 +560,8 @@ static PyTypeObject pylock_op_type = { .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, }; +#define PYTHON_PROC_MAX_ENV 32 + struct pyproc { PyObject_HEAD pid_t pid; diff --git a/src/python.c b/src/python.c @@ -72,6 +72,11 @@ struct reqcall { TAILQ_ENTRY(reqcall) list; }; +union deconst { + char *p; + const char *cp; +}; + TAILQ_HEAD(reqcall_list, reqcall); PyMODINIT_FUNC python_module_init(void); @@ -2722,12 +2727,15 @@ python_kore_timer(PyObject *self, PyObject *args, PyObject *kwargs) } static PyObject * -python_kore_proc(PyObject *self, PyObject *args) +python_kore_proc(PyObject *self, PyObject *args, PyObject *kwargs) { + union deconst cp; const char *cmd; struct pyproc *proc; - char *copy, *argv[32], *env[1]; + Py_ssize_t idx, len; + PyObject *obj, *item; int timeo, in_pipe[2], out_pipe[2]; + char *copy, *argv[32], *env[PYTHON_PROC_MAX_ENV + 1]; timeo = -1; @@ -2740,6 +2748,37 @@ python_kore_proc(PyObject *self, PyObject *args) if (!PyArg_ParseTuple(args, "s|i", &cmd, &timeo)) return (NULL); + if (kwargs != NULL && + (obj = PyDict_GetItemString(kwargs, "env")) != NULL) { + if (!PyList_CheckExact(obj)) { + PyErr_SetString(PyExc_RuntimeError, + "kore.proc: env is not of type 'list'"); + return (NULL); + } + + len = PyList_Size(obj); + if (len > PYTHON_PROC_MAX_ENV) { + PyErr_SetString(PyExc_RuntimeError, + "kore.proc: too many entries in 'env' keyword"); + return (NULL); + } + + for (idx = 0; idx < len; idx++) { + if ((item = PyList_GetItem(obj, idx)) == NULL) + return (NULL); + + if (!PyUnicode_CheckExact(item)) + return (NULL); + + if ((cp.cp = PyUnicode_AsUTF8(item)) == NULL) + return (NULL); + + env[idx] = cp.p; + } + + env[idx] = NULL; + } + if (pipe(in_pipe) == -1) { PyErr_SetString(PyExc_RuntimeError, errno_s); return (NULL); @@ -2796,7 +2835,6 @@ python_kore_proc(PyObject *self, PyObject *args) dup2(in_pipe[0], STDIN_FILENO) == -1) fatal("dup2: %s", errno_s); - env[0] = NULL; copy = kore_strdup(cmd); python_split_arguments(copy, argv, 32);