Files
uwsgi/pyutils.c
T
2010-09-11 14:49:02 +00:00

258 lines
6.8 KiB
C

#include "uwsgi.h"
int manage_python_response(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req) {
PyObject *pychunk ;
ssize_t wsize ;
#ifdef UWSGI_SENDFILE
ssize_t sf_len = 0 ;
#endif
// return or yield ?
if (PyString_Check((PyObject *)wsgi_req->async_result)) {
if ((wsize = write(wsgi_req->poll.fd, PyString_AsString(wsgi_req->async_result), PyString_Size(wsgi_req->async_result))) < 0) {
uwsgi_error("write()");
goto clear;
}
wsgi_req->response_size += wsize;
goto clear;
}
#ifdef PYTHREE
if (PyBytes_Check((PyObject *)wsgi_req->async_result)) {
if ((wsize = write(wsgi_req->poll.fd, PyBytes_AsString(wsgi_req->async_result), PyBytes_Size(wsgi_req->async_result))) < 0) {
uwsgi_error("write()");
goto clear;
}
wsgi_req->response_size += wsize;
goto clear;
}
#endif
#ifdef UWSGI_SENDFILE
if (wsgi_req->sendfile_obj == wsgi_req->async_result && wsgi_req->sendfile_fd != -1) {
sf_len = uwsgi_sendfile(uwsgi, wsgi_req);
if (sf_len < 1) goto clear;
wsgi_req->response_size += sf_len ;
#ifdef UWSGI_ASYNC
if (uwsgi->async > 1) {
if (wsgi_req->response_size < wsgi_req->sendfile_fd_size) {
return UWSGI_AGAIN;
}
}
#endif
goto clear;
}
#endif
#ifdef UWSGI_WSGI2
// is it a tuple (WSGI2.0) ?
// move it to another hook !!!
if (PyTuple_Check((PyObject *)wsgi_req->async_result)) {
if (PyTuple_Size((PyObject *)wsgi_req->async_result) != 3) {
uwsgi_log("invalid WSGI2.0 response size: %d.\n", PyTuple_Size((PyObject *)wsgi_req->async_result));
goto clear;
}
#ifdef UWSGI_DEBUG
uwsgi_debug("wsgi_req->async_result = %d\n", ((PyObject *)wsgi_req->async_result)->ob_refcnt);
#endif
if (py_uwsgi_spit(NULL, (PyObject *)wsgi_req->async_result) == Py_None) {
goto clear;
}
#ifdef UWSGI_DEBUG
uwsgi_debug("wsgi_req->async_result = %d\n", ((PyObject *)wsgi_req->async_result)->ob_refcnt);
#endif
wsgi_req->async_orig_result = wsgi_req->async_result ;
wsgi_req->async_result = PyTuple_GetItem((PyObject *)wsgi_req->async_result, 2);
#ifdef UWSGI_DEBUG
uwsgi_debug("wsgi_req->async_orig_result = %d\n", ((PyObject *)wsgi_req->async_orig_result)->ob_refcnt);
uwsgi_debug("wsgi_req->async_result = %d\n", ((PyObject *)wsgi_req->async_result)->ob_refcnt);
#endif
return UWSGI_AGAIN;
}
#endif
// ok its a yield
if (!wsgi_req->async_placeholder) {
wsgi_req->async_placeholder = PyObject_GetIter(wsgi_req->async_result);
if (!wsgi_req->async_placeholder) {
goto clear2;
}
#ifdef UWSGI_ASYNC
if (uwsgi->async > 1) {
return UWSGI_AGAIN;
}
#endif
}
pychunk = PyIter_Next(wsgi_req->async_placeholder) ;
if (!pychunk) {
if (PyErr_Occurred()) PyErr_Print();
goto clear;
}
if (PyString_Check(pychunk)) {
if ((wsize = write(wsgi_req->poll.fd, PyString_AsString(pychunk), PyString_Size(pychunk))) < 0) {
uwsgi_error("write()");
Py_DECREF(pychunk);
goto clear;
}
wsgi_req->response_size += wsize;
}
#ifdef PYTHREE
else if (PyBytes_Check(pychunk)) {
if ((wsize = write(wsgi_req->poll.fd, PyBytes_AsString(pychunk), PyBytes_Size(pychunk))) < 0) {
uwsgi_error("write()");
Py_DECREF(pychunk);
goto clear;
}
wsgi_req->response_size += wsize;
}
#endif
#ifdef UWSGI_SENDFILE
else if (wsgi_req->sendfile_obj == pychunk && wsgi_req->sendfile_fd != -1) {
sf_len = uwsgi_sendfile(uwsgi, wsgi_req);
if (sf_len < 1) goto clear;
wsgi_req->response_size += sf_len ;
}
#endif
Py_DECREF(pychunk);
return UWSGI_AGAIN ;
clear:
if (wsgi_req->sendfile_fd != -1) {
Py_DECREF((PyObject *)wsgi_req->async_sendfile);
}
if (wsgi_req->async_environ) {
PyDict_Clear(wsgi_req->async_environ);
}
if (wsgi_req->async_post && !wsgi_req->fd_closed) {
fclose(wsgi_req->async_post);
if (!uwsgi->post_buffering || wsgi_req->post_cl <= (size_t) uwsgi->post_buffering) {
wsgi_req->fd_closed = 1 ;
}
}
Py_XDECREF((PyObject *)wsgi_req->async_placeholder);
#ifdef UWSGI_WSGI2
Py_XDECREF((PyObject *)wsgi_req->async_orig_result);
#endif
clear2:
Py_DECREF((PyObject *)wsgi_req->async_result);
PyErr_Clear();
#ifdef UWSGI_DEBUG
if (wsgi_req->async_placeholder) {
uwsgi_debug("wsgi_req->async_placeholder: %d\n", ((PyObject *)wsgi_req->async_placeholder)->ob_refcnt);
}
#ifdef UWSGI_WSGI2
if (wsgi_req->async_orig_result) {
uwsgi_debug("wsgi_req->async_orig_result: %d\n", ((PyObject *)wsgi_req->async_orig_result)->ob_refcnt);
}
#endif
if (wsgi_req->async_result) {
uwsgi_debug("wsgi_req->async_result: %d\n", ((PyObject *)wsgi_req->async_result)->ob_refcnt);
}
if (wsgi_req->async_app) {
uwsgi_debug("wsgi_req->async_app: %d\n", ((PyObject *)wsgi_req->async_app)->ob_refcnt);
}
#endif
return UWSGI_OK;
}
PyObject *python_call(PyObject *callable, PyObject *args, int catch) {
PyObject *pyret;
pyret = PyEval_CallObject(callable, args);
if (PyErr_Occurred()) {
if (!catch) {
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 uwsgi_server *uwsgi, struct wsgi_request *wsgi_req, PyObject *callable, PyObject *args) {
wsgi_req->async_result = python_call(callable, args, 0);
if (wsgi_req->async_result) {
while ( manage_python_response(uwsgi, wsgi_req) != UWSGI_OK) {
#ifdef UWSGI_ASYNC
if (uwsgi->async > 1) {
return UWSGI_AGAIN;
}
#endif
}
}
return UWSGI_OK;
}
void init_pyargv(struct uwsgi_server *uwsgi) {
char *ap;
#ifdef PYTHREE
wchar_t pname[6];
mbstowcs(pname, "uwsgi", 6);
uwsgi->py_argv[0] = pname;
#else
uwsgi->py_argv[0] = "uwsgi";
#endif
if (uwsgi->pyargv != NULL && !uwsgi->pyargc) {
uwsgi->pyargc++;
#ifdef PYTHREE
wchar_t *wcargv = malloc( sizeof( wchar_t ) * (strlen(uwsgi->pyargv)+1));
if (!wcargv) {
uwsgi_error("malloc()");
exit(1);
}
memset(wcargv, 0, sizeof( wchar_t ) * (strlen(uwsgi->pyargv)+1));
#endif
#ifdef __sun__
// FIX THIS !!!
ap = strtok(uwsgi->pyargv, " ");
while ((ap = strtok(NULL, " ")) != NULL) {
#else
while ((ap = strsep(&uwsgi->pyargv, " \t")) != NULL) {
#endif
if (*ap != '\0') {
#ifdef PYTHREE
mbstowcs( wcargv + strlen(ap), ap, strlen(ap));
uwsgi->py_argv[uwsgi->pyargc] = wcargv + strlen(ap);
#else
uwsgi->py_argv[uwsgi->pyargc] = ap;
#endif
uwsgi->pyargc++;
}
if (uwsgi->pyargc + 1 > MAX_PYARGV)
break;
}
}
PySys_SetArgv(uwsgi->pyargc, uwsgi->py_argv);
}