mirror of
https://github.com/clearlinux/uwsgi.git
synced 2026-09-06 13:41:28 +00:00
completetd first part of the new exceptions framework
This commit is contained in:
@@ -271,7 +271,9 @@ int uwsgi_response_subhandler_pump(struct wsgi_request *wsgi_req) {
|
||||
pychunk = PyIter_Next(wsgi_req->async_placeholder);
|
||||
|
||||
if (!pychunk) {
|
||||
if (PyErr_Occurred()) PyErr_Print();
|
||||
if (PyErr_Occurred()) {
|
||||
uwsgi_manage_exception(wsgi_req, uwsgi.catch_exceptions);
|
||||
}
|
||||
goto clear;
|
||||
}
|
||||
|
||||
|
||||
@@ -822,11 +822,6 @@ void init_uwsgi_embedded_module() {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (PyDict_SetItemString(up.embedded_dict, "message_manager_marshal", Py_None)) {
|
||||
PyErr_Print();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
init_uwsgi_module_advanced(new_uwsgi_module);
|
||||
|
||||
if (uwsgi.spoolers) {
|
||||
@@ -1879,6 +1874,7 @@ struct uwsgi_plugin pypy_plugin = {
|
||||
.exception_msg = uwsgi_python_exception_msg,
|
||||
.exception_repr = uwsgi_python_exception_repr,
|
||||
.exception_log = uwsgi_python_exception_log,
|
||||
.backtrace = uwsgi_python_backtrace,
|
||||
|
||||
|
||||
};
|
||||
|
||||
+65
-61
@@ -41,56 +41,80 @@ char *uwsgi_python_get_exception_type(PyObject *exc) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *uwsgi_python_get_exception_value(PyObject *value) {
|
||||
return PyString_AsString( PyObject_Str(value) );
|
||||
}
|
||||
|
||||
char *uwsgi_python_get_exception_repr(PyObject *exc, PyObject *value) {
|
||||
char *exc_type = uwsgi_python_get_exception_type(exc);
|
||||
char *exc_value = uwsgi_python_get_exception_value(value);
|
||||
|
||||
if (exc_type && exc_value) {
|
||||
return uwsgi_concat3(exc_type, ": ", exc_value);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int uwsgi_python_manage_exceptions(void) {
|
||||
struct uwsgi_buffer *uwsgi_python_backtrace(struct wsgi_request *wsgi_req) {
|
||||
PyObject *type = NULL;
|
||||
PyObject *value = NULL;
|
||||
PyObject *traceback = NULL;
|
||||
|
||||
char *exc_type = NULL;
|
||||
char *exc_value = NULL;
|
||||
char *exc_repr = NULL;
|
||||
PyObject *value = NULL;
|
||||
PyObject *traceback = NULL;
|
||||
struct uwsgi_buffer *ub = NULL;
|
||||
|
||||
PyErr_Fetch(&type, &value, &traceback);
|
||||
PyErr_NormalizeException(&type, &value, &traceback);
|
||||
PyErr_NormalizeException(&type, &value, &traceback);
|
||||
|
||||
if (uwsgi.reload_on_exception_type) {
|
||||
exc_type = uwsgi_python_get_exception_type(type);
|
||||
// traceback could not be available
|
||||
if (!traceback) goto end;
|
||||
|
||||
PyObject *traceback_module = PyImport_ImportModule("traceback");
|
||||
if (!traceback_module) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (uwsgi.reload_on_exception_value) {
|
||||
exc_value = uwsgi_python_get_exception_value(value);
|
||||
PyObject *traceback_dict = PyModule_GetDict(traceback_module);
|
||||
PyObject *extract_tb = PyDict_GetItemString(traceback_dict, "extract_tb");
|
||||
if (!extract_tb) goto end;
|
||||
PyObject *args = PyTuple_New(1);
|
||||
Py_INCREF(traceback);
|
||||
PyTuple_SetItem(args, 0, traceback);
|
||||
PyObject *result = PyEval_CallObject(extract_tb, args);
|
||||
Py_DECREF(args);
|
||||
|
||||
if (!result) goto end;
|
||||
|
||||
ub = uwsgi_buffer_new(4096);
|
||||
Py_ssize_t i;
|
||||
// we have to build a uwsgi array with 5 items (4 are taken from the python tb)
|
||||
for(i=0;i< PyList_Size(result);i++) {
|
||||
PyObject *t = PyList_GetItem(result, i);
|
||||
PyObject *tb_filename = PyTuple_GetItem(t, 0);
|
||||
PyObject *tb_lineno = PyTuple_GetItem(t, 1);
|
||||
PyObject *tb_function = PyTuple_GetItem(t, 2);
|
||||
PyObject *tb_text = PyTuple_GetItem(t, 3);
|
||||
|
||||
int64_t line_no = PyInt_AsLong(tb_lineno);
|
||||
|
||||
// filename
|
||||
if (uwsgi_buffer_u16le(ub, PyString_Size(tb_filename))) goto end0;
|
||||
if (uwsgi_buffer_append(ub, PyString_AsString(tb_filename), PyString_Size(tb_filename))) goto end0;
|
||||
|
||||
// lineno
|
||||
if (uwsgi_buffer_append_valnum(ub, line_no)) goto end0;
|
||||
|
||||
// function
|
||||
if (uwsgi_buffer_u16le(ub, PyString_Size(tb_function))) goto end0;
|
||||
if (uwsgi_buffer_append(ub, PyString_AsString(tb_function), PyString_Size(tb_function))) goto end0;
|
||||
|
||||
// text
|
||||
if (uwsgi_buffer_u16le(ub, PyString_Size(tb_text))) goto end0;
|
||||
if (uwsgi_buffer_append(ub, PyString_AsString(tb_text), PyString_Size(tb_text))) goto end0;
|
||||
|
||||
// custom (unused)
|
||||
if (uwsgi_buffer_u16le(ub, 0)) goto end0;
|
||||
if (uwsgi_buffer_append(ub, "", 0)) goto end0;
|
||||
|
||||
}
|
||||
|
||||
if (uwsgi.reload_on_exception_repr) {
|
||||
exc_repr = uwsgi_python_get_exception_repr(type, value);
|
||||
}
|
||||
Py_DECREF(result);
|
||||
goto end;
|
||||
|
||||
int ret = uwsgi_manage_exception(exc_type, exc_value, exc_repr);
|
||||
|
||||
// free memory allocated for strcmp
|
||||
if (exc_type) free(exc_type);
|
||||
if (exc_repr) free(exc_repr);
|
||||
|
||||
PyErr_Restore(type, value, traceback);
|
||||
|
||||
return ret;
|
||||
end0:
|
||||
Py_DECREF(result);
|
||||
uwsgi_buffer_destroy(ub);
|
||||
ub = NULL;
|
||||
end:
|
||||
PyErr_Restore(type, value, traceback);
|
||||
return ub;
|
||||
}
|
||||
|
||||
|
||||
struct uwsgi_buffer *uwsgi_python_exception_class(struct wsgi_request *wsgi_req) {
|
||||
PyObject *type = NULL;
|
||||
PyObject *value = NULL;
|
||||
@@ -111,6 +135,7 @@ struct uwsgi_buffer *uwsgi_python_exception_class(struct wsgi_request *wsgi_req)
|
||||
}
|
||||
}
|
||||
end:
|
||||
free(class);
|
||||
PyErr_Restore(type, value, traceback);
|
||||
return ub;
|
||||
}
|
||||
@@ -183,28 +208,7 @@ PyObject *python_call(PyObject *callable, PyObject *args, int catch, struct wsgi
|
||||
//uwsgi_log("called\n");
|
||||
|
||||
if (PyErr_Occurred()) {
|
||||
|
||||
|
||||
int do_exit = uwsgi_python_manage_exceptions();
|
||||
|
||||
if (PyErr_ExceptionMatches(PyExc_MemoryError)) {
|
||||
uwsgi_log("Memory Error detected !!!\n");
|
||||
}
|
||||
|
||||
// this can be in a spooler or in the master
|
||||
if (uwsgi.mywid > 0) {
|
||||
uwsgi.workers[uwsgi.mywid].exceptions++;
|
||||
if (wsgi_req) {
|
||||
uwsgi_apps[wsgi_req->app_id].exceptions++;
|
||||
}
|
||||
}
|
||||
if (!catch) {
|
||||
PyErr_Print();
|
||||
}
|
||||
|
||||
if (do_exit) {
|
||||
exit(UWSGI_EXCEPTION_CODE);
|
||||
}
|
||||
uwsgi_manage_exception(wsgi_req, catch);
|
||||
}
|
||||
|
||||
#ifdef UWSGI_DEBUG
|
||||
|
||||
@@ -1898,58 +1898,6 @@ PyObject *py_uwsgi_async_connect(PyObject * self, PyObject * args) {
|
||||
return PyInt_FromLong(uwsgi_connect(socket_name, 0, 1));
|
||||
}
|
||||
|
||||
PyObject *py_uwsgi_async_send_message(PyObject * self, PyObject * args) {
|
||||
|
||||
PyObject *pyobj = NULL;
|
||||
|
||||
int uwsgi_fd;
|
||||
int modifier1 = 0;
|
||||
int modifier2 = 0;
|
||||
|
||||
char *encoded;
|
||||
uint16_t esize = 0;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "iiiO:async_send_message", &uwsgi_fd, &modifier1, &modifier2, &pyobj)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (uwsgi_fd < 0)
|
||||
goto clear;
|
||||
|
||||
// now check for the type of object to send (fallback to marshal)
|
||||
if (PyDict_Check(pyobj)) {
|
||||
encoded = uwsgi_encode_pydict(pyobj, &esize);
|
||||
if (esize > 0) {
|
||||
UWSGI_RELEASE_GIL uwsgi_send_message(uwsgi_fd, (uint8_t) modifier1, (uint8_t) modifier2, encoded, esize, -1, 0, 0);
|
||||
free(encoded);
|
||||
}
|
||||
}
|
||||
else if (PyString_Check(pyobj)) {
|
||||
encoded = PyString_AsString(pyobj);
|
||||
esize = PyString_Size(pyobj);
|
||||
UWSGI_RELEASE_GIL uwsgi_send_message(uwsgi_fd, (uint8_t) modifier1, (uint8_t) modifier2, encoded, esize, -1, 0, 0);
|
||||
}
|
||||
#ifndef UWSGI_PYPY
|
||||
else {
|
||||
PyObject *marshalled = PyMarshal_WriteObjectToString(pyobj, 1);
|
||||
if (!marshalled) {
|
||||
PyErr_Print();
|
||||
goto clear;
|
||||
}
|
||||
|
||||
encoded = PyString_AsString(marshalled);
|
||||
esize = PyString_Size(marshalled);
|
||||
UWSGI_RELEASE_GIL uwsgi_send_message(uwsgi_fd, (uint8_t) modifier1, (uint8_t) modifier2, encoded, esize, -1, 0, 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
UWSGI_GET_GIL clear:
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
|
||||
}
|
||||
|
||||
/* uWSGI masterpid */
|
||||
PyObject *py_uwsgi_masterpid(PyObject * self, PyObject * args) {
|
||||
if (uwsgi.master_process) {
|
||||
@@ -2014,7 +1962,7 @@ PyObject *py_uwsgi_workers(PyObject * self, PyObject * args) {
|
||||
}
|
||||
Py_DECREF(zero);
|
||||
|
||||
zero = PyLong_FromUnsignedLongLong(uwsgi.workers[i + 1].exceptions);
|
||||
zero = PyLong_FromUnsignedLongLong(uwsgi_worker_exceptions(i+1));
|
||||
if (PyDict_SetItemString(worker_dict, "exceptions", zero)) {
|
||||
goto clear;
|
||||
}
|
||||
@@ -2504,7 +2452,6 @@ static PyMethodDef uwsgi_advanced_methods[] = {
|
||||
#endif
|
||||
{"async_sleep", py_uwsgi_async_sleep, METH_VARARGS, ""},
|
||||
{"async_connect", py_uwsgi_async_connect, METH_VARARGS, ""},
|
||||
{"async_send_message", py_uwsgi_async_send_message, METH_VARARGS, ""},
|
||||
|
||||
{"green_schedule", py_uwsgi_suspend, METH_VARARGS, ""},
|
||||
{"suspend", py_uwsgi_suspend, METH_VARARGS, ""},
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
#endif
|
||||
|
||||
#define uwsgi_py_write_set_exception(x) if (!uwsgi.disable_write_exception) { PyErr_SetString(PyExc_IOError, "write error"); };
|
||||
#define uwsgi_py_write_exception(x) uwsgi_py_write_set_exception(x); PyErr_Print();
|
||||
#define uwsgi_py_write_exception(x) uwsgi_py_write_set_exception(x); uwsgi_manage_exception(x, 0);
|
||||
|
||||
|
||||
#define uwsgi_py_check_write_errors if (wsgi_req->write_errors > 0 && uwsgi.write_errors_exception_only) {\
|
||||
@@ -258,7 +258,6 @@ char *uwsgi_pythonize(char *);
|
||||
void *uwsgi_python_autoreloader_thread(void *);
|
||||
void *uwsgi_python_tracebacker_thread(void *);
|
||||
|
||||
int uwsgi_python_manage_exceptions(void);
|
||||
int uwsgi_python_do_send_headers(struct wsgi_request *);
|
||||
void *uwsgi_python_tracebacker_thread(void *);
|
||||
PyObject *uwsgi_python_setup_thread(char *);
|
||||
@@ -266,6 +265,7 @@ PyObject *uwsgi_python_setup_thread(char *);
|
||||
struct uwsgi_buffer *uwsgi_python_exception_class(struct wsgi_request *);
|
||||
struct uwsgi_buffer *uwsgi_python_exception_msg(struct wsgi_request *);
|
||||
struct uwsgi_buffer *uwsgi_python_exception_repr(struct wsgi_request *);
|
||||
struct uwsgi_buffer *uwsgi_python_backtrace(struct wsgi_request *);
|
||||
void uwsgi_python_exception_log(struct wsgi_request *);
|
||||
|
||||
#ifdef UWSGI_PYPY
|
||||
|
||||
@@ -178,7 +178,9 @@ int uwsgi_response_subhandler_web3(struct wsgi_request *wsgi_req) {
|
||||
pychunk = PyIter_Next(wsgi_req->async_placeholder);
|
||||
|
||||
if (!pychunk) {
|
||||
if (PyErr_Occurred()) PyErr_Print();
|
||||
if (PyErr_Occurred()) {
|
||||
uwsgi_manage_exception(wsgi_req, uwsgi.catch_exceptions);
|
||||
}
|
||||
goto clear;
|
||||
}
|
||||
|
||||
|
||||
@@ -378,11 +378,6 @@ int uwsgi_request_wsgi(struct wsgi_request *wsgi_req) {
|
||||
|
||||
}
|
||||
|
||||
else if (uwsgi.catch_exceptions) {
|
||||
uwsgi_exceptions_catch(wsgi_req);
|
||||
PyErr_Print();
|
||||
}
|
||||
|
||||
// this object must be freed/cleared always
|
||||
end:
|
||||
if (wsgi_req->async_input) {
|
||||
@@ -413,7 +408,7 @@ void uwsgi_after_request_wsgi(struct wsgi_request *wsgi_req) {
|
||||
UWSGI_GET_GIL
|
||||
PyObject *arh = python_call(up.after_req_hook, up.after_req_hook_args, 0, NULL);
|
||||
if (!arh) {
|
||||
PyErr_Print();
|
||||
uwsgi_manage_exception(wsgi_req, 0);
|
||||
}
|
||||
else {
|
||||
Py_DECREF(arh);
|
||||
|
||||
@@ -169,16 +169,7 @@ int uwsgi_response_subhandler_wsgi(struct wsgi_request *wsgi_req) {
|
||||
if (!pychunk) {
|
||||
exception:
|
||||
if (PyErr_Occurred()) {
|
||||
int do_exit = uwsgi_python_manage_exceptions();
|
||||
if (PyErr_ExceptionMatches(PyExc_MemoryError)) {
|
||||
uwsgi_log("Memory Error detected !!!\n");
|
||||
}
|
||||
uwsgi.workers[uwsgi.mywid].exceptions++;
|
||||
uwsgi_apps[wsgi_req->app_id].exceptions++;
|
||||
PyErr_Print();
|
||||
if (do_exit) {
|
||||
exit(UWSGI_EXCEPTION_CODE);
|
||||
}
|
||||
uwsgi_manage_exception(wsgi_req, uwsgi.catch_exceptions);
|
||||
}
|
||||
goto clear;
|
||||
}
|
||||
@@ -230,7 +221,7 @@ clear:
|
||||
#endif
|
||||
PyObject *close_method_output = PyEval_CallObject(close_method, close_method_args);
|
||||
if (PyErr_Occurred()) {
|
||||
PyErr_Print();
|
||||
uwsgi_manage_exception(wsgi_req, 0);
|
||||
}
|
||||
Py_DECREF(close_method_args);
|
||||
Py_XDECREF(close_method_output);
|
||||
|
||||
Reference in New Issue
Block a user