mirror of
https://github.com/clearlinux/uwsgi.git
synced 2026-04-28 19:03:37 +00:00
391 lines
9.7 KiB
C
391 lines
9.7 KiB
C
#include "uwsgi_python.h"
|
|
|
|
extern struct uwsgi_server uwsgi;
|
|
extern struct uwsgi_python up;
|
|
|
|
int manage_python_response(struct wsgi_request *wsgi_req) {
|
|
// use standard WSGI response parse
|
|
return uwsgi_response_subhandler_wsgi(wsgi_req);
|
|
}
|
|
|
|
char *uwsgi_python_get_exception_type(PyObject *exc) {
|
|
char *class_name = NULL;
|
|
#if !defined(PYTHREE)
|
|
if (PyClass_Check(exc)) {
|
|
class_name = PyString_AsString( ((PyClassObject*)(exc))->cl_name );
|
|
}
|
|
else {
|
|
#endif
|
|
class_name = (char *) ((PyTypeObject*)exc)->tp_name;
|
|
#if !defined(PYTHREE)
|
|
}
|
|
#endif
|
|
|
|
if (class_name) {
|
|
char *dot = strrchr(class_name, '.');
|
|
if (dot) class_name = dot+1;
|
|
|
|
PyObject *module_name = PyObject_GetAttrString(exc, "__module__");
|
|
if (module_name) {
|
|
#ifdef PYTHREE
|
|
char *mod_name = NULL;
|
|
PyObject *zero = PyUnicode_AsUTF8String(module_name);
|
|
if (zero) {
|
|
mod_name = PyString_AsString(zero);
|
|
}
|
|
#else
|
|
char *mod_name = PyString_AsString(module_name);
|
|
#endif
|
|
if (mod_name && strcmp(mod_name, "exceptions") ) {
|
|
char *ret = uwsgi_concat3(mod_name, ".", class_name);
|
|
#ifdef PYTHREE
|
|
Py_DECREF(zero);
|
|
#endif
|
|
Py_DECREF(module_name);
|
|
return ret;
|
|
}
|
|
Py_DECREF(module_name);
|
|
return uwsgi_str(class_name);
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
struct uwsgi_buffer *uwsgi_python_backtrace(struct wsgi_request *wsgi_req) {
|
|
PyObject *type = NULL;
|
|
PyObject *value = NULL;
|
|
PyObject *traceback = NULL;
|
|
struct uwsgi_buffer *ub = NULL;
|
|
|
|
PyErr_Fetch(&type, &value, &traceback);
|
|
PyErr_NormalizeException(&type, &value, &traceback);
|
|
|
|
// traceback could not be available
|
|
if (!traceback) goto end;
|
|
|
|
PyObject *traceback_module = PyImport_ImportModule("traceback");
|
|
if (!traceback_module) {
|
|
goto end;
|
|
}
|
|
|
|
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);
|
|
|
|
#ifdef PYTHREE
|
|
PyObject *zero = PyUnicode_AsUTF8String(tb_filename);
|
|
if (!zero) goto end0;
|
|
|
|
// filename
|
|
if (uwsgi_buffer_u16le(ub, PyString_Size(zero))) { Py_DECREF(zero); goto end0; }
|
|
if (uwsgi_buffer_append(ub, PyString_AsString(zero), PyString_Size(zero))) { Py_DECREF(zero); goto end0; }
|
|
|
|
Py_DECREF(zero);
|
|
|
|
// lineno
|
|
if (uwsgi_buffer_append_valnum(ub, line_no)) goto end0;
|
|
|
|
zero = PyUnicode_AsUTF8String(tb_function);
|
|
if (!zero) goto end0;
|
|
|
|
// function
|
|
if (uwsgi_buffer_u16le(ub, PyString_Size(zero))) { Py_DECREF(zero); goto end0; }
|
|
if (uwsgi_buffer_append(ub, PyString_AsString(zero), PyString_Size(zero))) { Py_DECREF(zero); goto end0; }
|
|
|
|
Py_DECREF(zero);
|
|
|
|
zero = PyUnicode_AsUTF8String(tb_text);
|
|
if (!zero) goto end0;
|
|
|
|
// text
|
|
if (uwsgi_buffer_u16le(ub, PyString_Size(zero))) { Py_DECREF(zero); goto end0; }
|
|
if (uwsgi_buffer_append(ub, PyString_AsString(zero), PyString_Size(zero))) { Py_DECREF(zero); goto end0; }
|
|
|
|
Py_DECREF(zero);
|
|
|
|
#else
|
|
// 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;
|
|
#endif
|
|
|
|
// custom (unused)
|
|
if (uwsgi_buffer_u16le(ub, 0)) goto end0;
|
|
if (uwsgi_buffer_append(ub, "", 0)) goto end0;
|
|
|
|
}
|
|
|
|
Py_DECREF(result);
|
|
goto end;
|
|
|
|
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;
|
|
PyObject *traceback = NULL;
|
|
struct uwsgi_buffer *ub = NULL;
|
|
|
|
PyErr_Fetch(&type, &value, &traceback);
|
|
PyErr_NormalizeException(&type, &value, &traceback);
|
|
|
|
char *class = uwsgi_python_get_exception_type(type);
|
|
if (class) {
|
|
size_t class_len = strlen(class);
|
|
ub = uwsgi_buffer_new(class_len);
|
|
if (uwsgi_buffer_append(ub, class, class_len)) {
|
|
uwsgi_buffer_destroy(ub);
|
|
ub = NULL;
|
|
goto end;
|
|
}
|
|
}
|
|
end:
|
|
free(class);
|
|
PyErr_Restore(type, value, traceback);
|
|
return ub;
|
|
}
|
|
|
|
struct uwsgi_buffer *uwsgi_python_exception_msg(struct wsgi_request *wsgi_req) {
|
|
PyObject *type = NULL;
|
|
PyObject *value = NULL;
|
|
PyObject *traceback = NULL;
|
|
struct uwsgi_buffer *ub = NULL;
|
|
|
|
PyErr_Fetch(&type, &value, &traceback);
|
|
PyErr_NormalizeException(&type, &value, &traceback);
|
|
|
|
// value could be NULL ?
|
|
if (!value) goto end;
|
|
|
|
#ifdef PYTHREE
|
|
char *msg = NULL;
|
|
PyObject *zero = PyUnicode_AsUTF8String( PyObject_Str(value) );
|
|
if (zero) {
|
|
msg = PyString_AsString( zero );
|
|
}
|
|
#else
|
|
char *msg = PyString_AsString( PyObject_Str(value) );
|
|
#endif
|
|
if (msg) {
|
|
size_t msg_len = strlen(msg);
|
|
ub = uwsgi_buffer_new(msg_len);
|
|
if (uwsgi_buffer_append(ub, msg, msg_len)) {
|
|
#ifdef PYTHREE
|
|
Py_DECREF(zero);
|
|
#endif
|
|
uwsgi_buffer_destroy(ub);
|
|
ub = NULL;
|
|
goto end;
|
|
}
|
|
#ifdef PYTHREE
|
|
Py_DECREF(zero);
|
|
#endif
|
|
}
|
|
end:
|
|
PyErr_Restore(type, value, traceback);
|
|
return ub;
|
|
}
|
|
|
|
struct uwsgi_buffer *uwsgi_python_exception_repr(struct wsgi_request *wsgi_req) {
|
|
|
|
struct uwsgi_buffer *ub_class = uwsgi_python_exception_class(wsgi_req);
|
|
if (!ub_class) return NULL;
|
|
|
|
struct uwsgi_buffer *ub_msg = uwsgi_python_exception_msg(wsgi_req);
|
|
if (!ub_msg) {
|
|
uwsgi_buffer_destroy(ub_class);
|
|
return NULL;
|
|
}
|
|
|
|
struct uwsgi_buffer *ub = uwsgi_buffer_new(ub_class->pos + 2 + ub_msg->pos);
|
|
if (uwsgi_buffer_append(ub, ub_class->buf, ub_class->pos)) goto error;
|
|
if (uwsgi_buffer_append(ub, ": ", 2)) goto error;
|
|
if (uwsgi_buffer_append(ub, ub_msg->buf, ub_msg->pos)) goto error;
|
|
|
|
uwsgi_buffer_destroy(ub_class);
|
|
uwsgi_buffer_destroy(ub_msg);
|
|
|
|
return ub;
|
|
|
|
error:
|
|
uwsgi_buffer_destroy(ub_class);
|
|
uwsgi_buffer_destroy(ub_msg);
|
|
uwsgi_buffer_destroy(ub);
|
|
return NULL;
|
|
}
|
|
|
|
void uwsgi_python_exception_log(struct wsgi_request *wsgi_req) {
|
|
PyErr_Print();
|
|
}
|
|
|
|
PyObject *python_call(PyObject *callable, PyObject *args, int catch, struct wsgi_request *wsgi_req) {
|
|
|
|
//uwsgi_log("ready to call %p %p\n", callable, args);
|
|
|
|
PyObject *pyret = PyEval_CallObject(callable, args);
|
|
|
|
//uwsgi_log("called\n");
|
|
|
|
if (PyErr_Occurred()) {
|
|
if (wsgi_req) {
|
|
uwsgi_manage_exception(wsgi_req, catch);
|
|
}
|
|
else {
|
|
PyErr_Print();
|
|
}
|
|
}
|
|
|
|
#ifdef UWSGI_DEBUG
|
|
if (pyret) {
|
|
uwsgi_debug("called %p %p %d\n", callable, args, pyret->ob_refcnt);
|
|
}
|
|
#endif
|
|
|
|
return pyret;
|
|
}
|
|
|
|
int uwsgi_python_call(struct wsgi_request *wsgi_req, PyObject *callable, PyObject *args) {
|
|
|
|
wsgi_req->async_result = python_call(callable, args, 0, wsgi_req);
|
|
|
|
if (wsgi_req->async_result) {
|
|
while ( manage_python_response(wsgi_req) != UWSGI_OK) {
|
|
if (uwsgi.async > 0) {
|
|
return UWSGI_AGAIN;
|
|
}
|
|
}
|
|
}
|
|
|
|
return UWSGI_OK;
|
|
}
|
|
|
|
void init_pyargv() {
|
|
|
|
char *ap;
|
|
|
|
char *argv0 = "uwsgi";
|
|
|
|
if (up.pyrun) {
|
|
argv0 = up.pyrun;
|
|
}
|
|
|
|
#ifdef PYTHREE
|
|
wchar_t *pname = uwsgi_calloc(sizeof(wchar_t) * (strlen(argv0)+1));
|
|
mbstowcs(pname, argv0, strlen(argv0)+1);
|
|
#else
|
|
char *pname = argv0;
|
|
#endif
|
|
|
|
up.argc = 1;
|
|
if (up.argv) {
|
|
char *tmp_ptr = uwsgi_str(up.argv);
|
|
#ifdef __sun__
|
|
// FIX THIS !!!
|
|
char *ctx = NULL;
|
|
ap = strtok_r(tmp_ptr, " ", &ctx);
|
|
while ((ap = strtok_r(NULL, " ", &ctx)) != NULL) {
|
|
#else
|
|
while ((ap = strsep(&tmp_ptr, " \t")) != NULL) {
|
|
#endif
|
|
if (*ap != '\0') {
|
|
up.argc++;
|
|
}
|
|
}
|
|
|
|
free(tmp_ptr);
|
|
}
|
|
|
|
#ifdef PYTHREE
|
|
up.py_argv = uwsgi_calloc(sizeof(wchar_t *) * up.argc+1);
|
|
#else
|
|
up.py_argv = uwsgi_calloc(sizeof(char *) * up.argc+1);
|
|
#endif
|
|
|
|
up.py_argv[0] = pname;
|
|
|
|
|
|
if (up.argv) {
|
|
|
|
char *py_argv_copy = uwsgi_str(up.argv);
|
|
up.argc = 1;
|
|
#ifdef PYTHREE
|
|
wchar_t *wcargv = uwsgi_calloc( sizeof( wchar_t ) * (strlen(py_argv_copy)+1));
|
|
#endif
|
|
|
|
#ifdef __sun__
|
|
// FIX THIS !!!
|
|
char *ctx = NULL;
|
|
ap = strtok_r(py_argv_copy, " ", &ctx);
|
|
while ((ap = strtok_r(NULL, " ", &ctx)) != NULL) {
|
|
#else
|
|
while ((ap = strsep(&py_argv_copy, " \t")) != NULL) {
|
|
#endif
|
|
if (*ap != '\0') {
|
|
#ifdef PYTHREE
|
|
mbstowcs( wcargv, ap, strlen(ap));
|
|
up.py_argv[up.argc] = wcargv;
|
|
wcargv += strlen(ap) + 1;
|
|
#else
|
|
up.py_argv[up.argc] = ap;
|
|
#endif
|
|
up.argc++;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
PySys_SetArgv(up.argc, up.py_argv);
|
|
|
|
PyObject *sys_dict = get_uwsgi_pydict("sys");
|
|
if (!sys_dict) {
|
|
uwsgi_log("unable to load python sys module !!!\n");
|
|
exit(1);
|
|
}
|
|
#ifdef PYTHREE
|
|
PyDict_SetItemString(sys_dict, "executable", PyUnicode_FromString(uwsgi.binary_path));
|
|
#else
|
|
PyDict_SetItemString(sys_dict, "executable", PyString_FromString(uwsgi.binary_path));
|
|
#endif
|
|
|
|
|
|
}
|