diff --git a/plugins/psgi/psgi.h b/plugins/psgi/psgi.h index db4326c7..4bc201e7 100644 --- a/plugins/psgi/psgi.h +++ b/plugins/psgi/psgi.h @@ -63,6 +63,8 @@ struct uwsgi_perl { char *shell; int shell_oneshot; + + CV *spooler; }; void init_perl_embedded_module(void); diff --git a/plugins/psgi/psgi_plugin.c b/plugins/psgi/psgi_plugin.c index 5db391be..ac587687 100644 --- a/plugins/psgi/psgi_plugin.c +++ b/plugins/psgi/psgi_plugin.c @@ -889,6 +889,59 @@ static void uwsgi_perl_hijack(void) { } +static void uwsgi_perl_add_item(char *key, uint16_t keylen, char *val, uint16_t vallen, void *data) { + + HV *spool_dict = (HV*) data; + + hv_store(spool_dict, key, keylen, newSVpv(val, vallen), 0); +} + + +static int uwsgi_perl_spooler(char *filename, char *buf, uint16_t len, char *body, size_t body_len) { + + int ret = -1; + + if (!uperl.spooler) return 0; + + dSP; + ENTER; + SAVETMPS; + PUSHMARK(SP); + + HV *spool_dict = newHV(); + + if (uwsgi_hooked_parse(buf, len, uwsgi_perl_add_item, (void *) spool_dict)) { + return 0; + } + + hv_store(spool_dict, "spooler_task_name", 18, newSVpv(filename, 0), 0); + + if (body && body_len > 0) { + hv_store(spool_dict, "body", 4, newSVpv(body, body_len), 0); + } + + XPUSHs( sv_2mortal((SV*)newRV_noinc((SV*)spool_dict)) ); + PUTBACK; + + call_sv( SvRV((SV*)uperl.spooler), G_SCALAR|G_EVAL); + + SPAGAIN; + if(SvTRUE(ERRSV)) { + uwsgi_log("[uwsgi-spooler-perl error] %s", SvPV_nolen(ERRSV)); + ret = -1; + } + else { + ret = POPi; + } + + PUTBACK; + FREETMPS; + LEAVE; + + return ret; +} + + struct uwsgi_plugin psgi_plugin = { @@ -916,4 +969,6 @@ struct uwsgi_plugin psgi_plugin = { .atexit = uwsgi_perl_atexit, .magic = uwsgi_perl_magic, + + .spooler = uwsgi_perl_spooler, }; diff --git a/plugins/psgi/uwsgi_plmodule.c b/plugins/psgi/uwsgi_plmodule.c index 4471e591..b62ff3be 100644 --- a/plugins/psgi/uwsgi_plmodule.c +++ b/plugins/psgi/uwsgi_plmodule.c @@ -245,6 +245,13 @@ XS(XS_register_signal) { } +XS(XS_spooler) { + dXSARGS; + psgi_check_args(1); + uperl.spooler = (CV *) newRV_inc(ST(0)); + XSRETURN_YES; +} + XS(XS_register_rpc) { dXSARGS; @@ -948,4 +955,6 @@ void init_perl_embedded_module() { psgi_xs(sharedarea_readfast); psgi_xs(sharedarea_write); psgi_xs(sharedarea_wait); + + psgi_xs(spooler); } diff --git a/plugins/python/python_plugin.c b/plugins/python/python_plugin.c index 934699dd..cc7beccb 100644 --- a/plugins/python/python_plugin.c +++ b/plugins/python/python_plugin.c @@ -1585,7 +1585,11 @@ void uwsgi_python_add_item(char *key, uint16_t keylen, char *val, uint16_t valle PyObject *pydict = (PyObject *) data; - PyDict_SetItem(pydict, PyString_FromStringAndSize(key, keylen), PyString_FromStringAndSize(val, vallen)); + PyObject *o_key = PyString_FromStringAndSize(key, keylen); + PyObject *zero = PyString_FromStringAndSize(val, vallen); + PyDict_SetItem(pydict, o_key, zero); + Py_DECREF(o_key); + Py_DECREF(zero); } int uwsgi_python_spooler(char *filename, char *buf, uint16_t len, char *body, size_t body_len) { @@ -1594,9 +1598,6 @@ int uwsgi_python_spooler(char *filename, char *buf, uint16_t len, char *body, si UWSGI_GET_GIL; - PyObject *spool_dict = PyDict_New(); - PyObject *spool_func, *pyargs, *ret; - if (!random_seed_reset) { uwsgi_python_reset_random_seed(); random_seed_reset = 1; @@ -1608,14 +1609,19 @@ int uwsgi_python_spooler(char *filename, char *buf, uint16_t len, char *body, si return 0; } - spool_func = PyDict_GetItemString(up.embedded_dict, "spooler"); + PyObject *spool_func = PyDict_GetItemString(up.embedded_dict, "spooler"); if (!spool_func) { // ignore UWSGI_RELEASE_GIL; return 0; } + PyObject *spool_dict = PyDict_New(); + PyObject *pyargs, *ret; + + if (uwsgi_hooked_parse(buf, len, uwsgi_python_add_item, spool_dict)) { + Py_DECREF(spool_dict); // malformed packet, destroy it UWSGI_RELEASE_GIL; return -2; @@ -1623,7 +1629,9 @@ int uwsgi_python_spooler(char *filename, char *buf, uint16_t len, char *body, si pyargs = PyTuple_New(1); - PyDict_SetItemString(spool_dict, "spooler_task_name", PyString_FromString(filename)); + PyObject *zero = PyString_FromString(filename); + PyDict_SetItemString(spool_dict, "spooler_task_name", zero); + Py_DECREF(zero); if (body && body_len > 0) { PyDict_SetItemString(spool_dict, "body", PyString_FromStringAndSize(body, body_len)); @@ -1634,12 +1642,18 @@ int uwsgi_python_spooler(char *filename, char *buf, uint16_t len, char *body, si if (ret) { if (!PyInt_Check(ret)) { + Py_DECREF(ret); + Py_DECREF(spool_dict); + Py_DECREF(pyargs); // error, retry UWSGI_RELEASE_GIL; return -1; } int retval = (int) PyInt_AsLong(ret); + Py_DECREF(ret); + Py_DECREF(spool_dict); + Py_DECREF(pyargs); UWSGI_RELEASE_GIL; return retval; @@ -1648,6 +1662,9 @@ int uwsgi_python_spooler(char *filename, char *buf, uint16_t len, char *body, si if (PyErr_Occurred()) PyErr_Print(); + Py_DECREF(spool_dict); + Py_DECREF(pyargs); + // error, retry UWSGI_RELEASE_GIL; return -1;