From de7269f833adabcbdf39ae93edf8e7920739294a Mon Sep 17 00:00:00 2001 From: Yann Weber Date: Sun, 4 Aug 2019 11:36:26 +0200 Subject: [PATCH] Deleted loglines, updated README + add check on FCGX_PutStr calls --- README | 24 ++++++++----- include/python_pyfcgi.h | 2 ++ src/python_pyfcgi.c | 76 +++++++++++++++++++++++++++-------------- src/pyworker.c | 8 ++--- 4 files changed, 69 insertions(+), 41 deletions(-) diff --git a/README b/README index e5c86e9..3df1fc8 100644 --- a/README +++ b/README @@ -8,17 +8,23 @@ Building & running pyfcgi : $ ./autogen.sh $ ./configure $ make - - $ spawn-fcgi -d . -n -p 9000 -a 127.0.0.1 -- src/pyfcgi -S -e foo -E entrypoint -A -or + # To run foo_pep333.entrypoint() PEP333 application $ spawn-fcgi -d . -n -p 9000 -a 127.0.0.1 -- src/pyfcgi -S -e foo_pep333 -E entrypoint +or + # To run foo.entrypoint() sending to FCGI python stdout + $ spawn-fcgi -d . -n -p 9000 -a 127.0.0.1 -- src/pyfcgi -S -e foo -E entrypoint -A + + +configure script determine python flags, libs & includes paths using +python3-config programm. The path can be specified using the +PYTHON_CONFIG_PATH environment variable. + +Example : linking against a debug build of python : +--------- + $ ./configure PYTHON_CONFIG_PATH=/usr/bin/python3dm-config --enable-debug + $ make clean && make + $ valgrind --log-file=/tmp/val.log --trace-children=yes spawn-fcgi -d . -n -p 9000 -a 127.0.0.1 -- src/pyfcgi -S -e foo_pep333 -E entrypoint -L '/tmp/foo.log;0xff;{datetime} {msg} {ident}' logging to file example : ------------------------- -L '/tmp/foo.log;0xff;{datetime} {msg} {ident}' - -Debugging : ------------ - $ ./configure PYTHON_CONFIG_PATH=/usr/bin/python3dm-config --enable-debug - $ make clean && make - $ valgrind --log-file=/tmp/val.log --trace-children=yes spawn-fcgi -d . -n -p 9000 -a 127.0.0.1 -- src/pyfcgi -S -e foo_pep333 -E entrypoint -L '/tmp/foo.log;0xff;{datetime} {msg} {ident}' diff --git a/include/python_pyfcgi.h b/include/python_pyfcgi.h index 58cdb39..55e1ac9 100644 --- a/include/python_pyfcgi.h +++ b/include/python_pyfcgi.h @@ -72,6 +72,7 @@ struct libpyfcgi_context_s size_t heads_buf_sz; /**@brief Persistent buffer for PEP333 status */ char status_buf[LIBPYFCGI_STATUS_SZ]; + size_t rep_sz; }; typedef struct libpyfcgi_context_s libpyfcgi_context_t; @@ -91,6 +92,7 @@ inline void libpyfcgi_clean_response() if(libpyfcgi.headers) { Py_DECREF(libpyfcgi.headers); } libpyfcgi.headers = NULL; libpyfcgi.headers_sent = 0; + libpyfcgi.rep_sz = 0; } /**@brief Send headers stored in @ref libpyfcgi context diff --git a/src/python_pyfcgi.c b/src/python_pyfcgi.c index 1c66e00..c54e792 100644 --- a/src/python_pyfcgi.c +++ b/src/python_pyfcgi.c @@ -123,12 +123,6 @@ void libpyfcgi_set_headers_buf() return; } -repr = PyObject_ASCII(libpyfcgi.headers); -Py_INCREF(repr); -pyfcgi_log(LOG_DEBUG, "Sending headers : '%s'", PyUnicode_AsUTF8(repr)); -Py_DECREF(repr); - - heads_iter = PyObject_GetIter(libpyfcgi.headers); if(!heads_iter) { @@ -257,6 +251,9 @@ head_decode_err: void libpyfcgi_send_headers() { + size_t sz; + int ret; + if(!libpyfcgi.out) { // invalid context @@ -279,11 +276,20 @@ void libpyfcgi_send_headers() log_expt(LOG_ALERT); exit(PYFCGI_FATAL); } -pyfcgi_log(LOG_DEBUG, "Headers ready to be sent : '%s'", libpyfcgi.heads_buf); - FCGX_PutStr(libpyfcgi.heads_buf, strlen(libpyfcgi.heads_buf), - libpyfcgi.out); -pyfcgi_log(LOG_DEBUG, "Headers sent..."); - FCGX_PutStr("\r\n", 2, libpyfcgi.out); + sz = strlen(libpyfcgi.heads_buf); + ret = FCGX_PutStr(libpyfcgi.heads_buf, sz, libpyfcgi.out); + if(ret < 0 ) + { + pyfcgi_log(LOG_ERR, "Unable to send headers"); + return; + } + libpyfcgi.rep_sz += ret; + ret = FCGX_PutStr("\r\n", 2, libpyfcgi.out); + if(ret < 0) + { + pyfcgi_log(LOG_ALERT, "Unable to send last \r\n from headers !"); + } + libpyfcgi.rep_sz += ret; libpyfcgi.headers_sent = 1; } @@ -297,6 +303,7 @@ PyInit_libpyfcgi(void) // init module & globals libpyfcgi.status = NULL; libpyfcgi.headers = NULL; + libpyfcgi.rep_sz = 0; libpyfcgi.self = PyModule_Create(&pyfcgimodule); if(libpyfcgi.self == NULL) { return NULL; } return libpyfcgi.self; @@ -336,10 +343,6 @@ PyObject* pyfcgi_start_response(PyObject* self, PyObject** argv, Py_ssize_t argc exc_info */ } -PyObject *repr = PyObject_ASCII(libpyfcgi.headers); -pyfcgi_log(LOG_DEBUG, "start_response called, headers : '%s'", PyUnicode_AsUTF8(repr)); -Py_DECREF(repr); - return PyObject_GetAttrString(self, "write_body"); } @@ -347,7 +350,6 @@ PyObject* pyfcgi_write_body(PyObject* self, PyObject** argv, Py_ssize_t argc) { char err[128]; -pyfcgi_log(LOG_DEBUG, "Write body called..."); if(argc != 1) { snprintf(err, 128, @@ -366,6 +368,7 @@ PyObject* _pyfcgi_write_body(PyObject *body_data) const char *dat; PyObject *bytes, *cur, *iter, *repr; Py_ssize_t sz; + int ret; if(!libpyfcgi.out) @@ -397,7 +400,6 @@ PyObject* _pyfcgi_write_body(PyObject *body_data) { Py_INCREF(iter); cur = PyIter_Next(iter); -pyfcgi_log(LOG_DEBUG, "Got iter for writing body..."); } if(!cur) @@ -409,7 +411,7 @@ pyfcgi_log(LOG_DEBUG, "Got iter for writing body..."); // if headers not sent yet, send them.... if(!libpyfcgi.headers_sent) { -pyfcgi_log(LOG_DEBUG, "Headers not sent... sending them..."); + pyfcgi_log(LOG_DEBUG, "Headers not sent... sending them..."); libpyfcgi_send_headers(); } @@ -422,13 +424,14 @@ pyfcgi_log(LOG_DEBUG, "Headers not sent... sending them..."); dat = PyUnicode_AsUTF8AndSize(cur, &sz); if(!dat) { + if(PyErr_Occurred()) { goto err_clean; } repr = PyObject_ASCII(cur); snprintf(err, 128, "libpyfcgi.__write_body unable to encode string as UTF-8 : %s", PyUnicode_AsUTF8(repr)); Py_DECREF(repr); PyErr_SetString(PyExc_ValueError, err); - Py_RETURN_NONE; + goto err_clean; } } else if(PyBytes_Check(cur)) @@ -436,8 +439,12 @@ pyfcgi_log(LOG_DEBUG, "Headers not sent... sending them..."); dat = PyBytes_AsString(cur); if(!dat) { - /**@todo if no expt set, set error str */ - Py_RETURN_NONE; + if(PyErr_Occurred()) { goto err_clean; } + + snprintf(err, 128, + "Unable to get bytes buffer when sending body data"); + PyErr_SetString(PyExc_ValueError, err); + goto err_clean; } sz = PyBytes_GET_SIZE(cur); } @@ -446,25 +453,36 @@ pyfcgi_log(LOG_DEBUG, "Headers not sent... sending them..."); bytes = PyObject_Bytes(cur); if(!bytes) { + if(PyErr_Occurred()) { goto err_clean; } + repr = PyObject_ASCII(cur); snprintf(err, 128, "libpyfcgi.__write_body expected str or bytes but %s given", PyUnicode_AsUTF8(repr)); Py_DECREF(repr); PyErr_SetString(PyExc_ValueError, err); - Py_RETURN_NONE; + goto err_clean; } dat = PyBytes_AsString(cur); if(!dat) { - /**@todo if no expt set, set error str */ - Py_RETURN_NONE; + if(PyErr_Occurred()) { goto err_clean; } + + snprintf(err, 128, + "Unable to get bytes buffer when sending body data"); + PyErr_SetString(PyExc_ValueError, err); + goto err_clean; } sz = PyBytes_GET_SIZE(cur); } -pyfcgi_log(LOG_DEBUG, "Sending '%s'", dat); - FCGX_PutStr(dat, sz, libpyfcgi.out); + ret = FCGX_PutStr(dat, sz, libpyfcgi.out); + if(ret < 0) + { + pyfcgi_log(LOG_ALERT, "Unable to send reply"); + goto err_clean; + } + libpyfcgi.rep_sz += ret; if(bytes) { Py_DECREF(bytes); } Py_DECREF(cur); @@ -475,4 +493,10 @@ pyfcgi_log(LOG_DEBUG, "Sending '%s'", dat); Py_DECREF(iter); } Py_RETURN_NONE; + +err_clean: + if(bytes) { Py_DECREF(bytes); } + Py_DECREF(cur); + if(iter) { Py_DECREF(iter); } + Py_RETURN_NONE; } diff --git a/src/pyworker.c b/src/pyworker.c index 11dc647..95202d2 100644 --- a/src/pyworker.c +++ b/src/pyworker.c @@ -85,14 +85,12 @@ int work333(int wrk_id, int semid) { gettimeofday(&start, NULL); worker_set_busy(semid); -pyfcgi_log(LOG_DEBUG, "Working !!"); count++; environ = update_pyenv(py_osmod, envp); libpyfcgi_clean_response(); libpyfcgi.out = out_stream; args = Py_BuildValue("OO", environ, start_response); -pyfcgi_log(LOG_DEBUG, "Calling entrypoint :D"); entry_ret = PyObject_CallObject(entry_fun, args); Py_INCREF(entry_ret); @@ -102,13 +100,11 @@ pyfcgi_log(LOG_DEBUG, "Calling entrypoint :D"); } // able to process returned value // Simulate python call of libpyfcgi.write_body() -pyfcgi_log(LOG_DEBUG, "Writing body !"); _pyfcgi_write_body(entry_ret); if(PyErr_Occurred()) { log_expt(LOG_ERR); } -pyfcgi_log(LOG_DEBUG, "Cleaning..."); // clean stuffs Py_DECREF(args); @@ -131,8 +127,8 @@ pyfcgi_log(LOG_DEBUG, "Cleaning..."); stop.tv_usec += 1000000; stop.tv_sec -= 1; } - pyfcgi_log(LOG_DEBUG, "Worker[%d] request %d END [OK] in %ld.%06lds", - wrk_id, count, stop.tv_sec, stop.tv_usec); + pyfcgi_log(LOG_DEBUG, "Worker[%d] request %d END [OK] %lu bytes in %ld.%06lds", + wrk_id, count, libpyfcgi.rep_sz, stop.tv_sec, stop.tv_usec); } return 0; }