add new files to the tree

This commit is contained in:
roberto@sirius
2010-10-20 21:55:37 +02:00
parent f7aa451af4
commit be183bf07f
13 changed files with 2552 additions and 0 deletions
+33
View File
@@ -0,0 +1,33 @@
[uwsgi]
xml = true
ini = true
snmp = true
sctp = false
erlang = false
spooler = false
embedded = false
udp = true
multicast = false
threading = true
sendfile = true
nagios = true
proxy = true
minterpreters = true
async = true
ugreen = false
http = true
evdis = false
ldap = true
routing = false
stackless = false
debug = true
unbit = false
xml_implementation = libxml2
plugins = python
bin_name = uwsgi
plugin_dir = .
embedded_plugins =
[python]
paste = true
web3 = true
Binary file not shown.
+19
View File
@@ -0,0 +1,19 @@
#include "uwsgi_python.h"
extern struct uwsgi_server uwsgi;
extern struct uwsgi_python up;
void gil_real_get() {
PyEval_AcquireLock();
PyThreadState_Swap((PyThreadState *) pthread_getspecific(up.upt_save_key));
}
void gil_real_release() {
pthread_setspecific(up.upt_save_key, (void *) PyThreadState_Swap(NULL));
PyEval_ReleaseLock();
}
void gil_fake_get() {}
void gil_fake_release() {}
+593
View File
@@ -0,0 +1,593 @@
#include "uwsgi_python.h"
/* notes
exit(1) on every malloc error: apps can be dinamically loaded so on memory problem
it is better to let the master process manager respawn the worker.
*/
extern struct uwsgi_server uwsgi;
extern struct uwsgi_python up;
#ifdef UWSGI_SENDFILE
PyMethodDef uwsgi_sendfile_method[] = {{"uwsgi_sendfile", py_uwsgi_sendfile, METH_VARARGS, ""}};
#endif
#ifdef UWSGI_ASYNC
PyMethodDef uwsgi_eventfd_read_method[] = { {"uwsgi_eventfd_read", py_eventfd_read, METH_VARARGS, ""}};
PyMethodDef uwsgi_eventfd_write_method[] = { {"uwsgi_eventfd_write", py_eventfd_write, METH_VARARGS, ""}};
#endif
int init_uwsgi_app(int loader, void *arg1, struct wsgi_request *wsgi_req, int new_interpreter) {
PyObject *zero;
int id = uwsgi.apps_cnt;
#ifdef UWSGI_ASYNC
int i;
#endif
char *mountpoint;
struct uwsgi_app *wi;
if (wsgi_req->script_name_len == 0) {
wsgi_req->script_name = "";
if (!uwsgi.vhost) id = 0;
}
else if (wsgi_req->script_name_len == 1) {
if (wsgi_req->script_name[0] == '/') {
if (!uwsgi.vhost) id = 0;
}
}
if (uwsgi.vhost && wsgi_req->host_len > 0) {
mountpoint = uwsgi_concat3n(wsgi_req->host, wsgi_req->host_len, "|", 1, wsgi_req->script_name, wsgi_req->script_name_len);
}
else {
mountpoint = uwsgi_strncopy(wsgi_req->script_name, wsgi_req->script_name_len);
}
if (uwsgi_get_app_id(mountpoint, strlen(mountpoint)) != -1) {
uwsgi_log( "mountpoint %.*s already configured. skip.\n", strlen(mountpoint), mountpoint);
free(mountpoint);
return -1;
}
wi = &uwsgi.apps[id];
memset(wi, 0, sizeof(struct uwsgi_app));
wi->mountpoint = mountpoint;
wi->mountpoint_len = strlen(mountpoint);
// dynamic chdir ?
if (wsgi_req->chdir_len > 0) {
wi->chdir = uwsgi_strncopy(wsgi_req->chdir, wsgi_req->chdir_len);
#ifdef UWSGI_DEBUG
uwsgi_debug("chdir to %s\n", wi->chdir);
#endif
if (chdir(wi->chdir)) {
uwsgi_error("chdir()");
}
}
// Initialize a new environment for the new interpreter
if (new_interpreter && id) {
wi->interpreter = Py_NewInterpreter();
if (!wi->interpreter) {
uwsgi_log( "unable to initialize the new python interpreter\n");
exit(1);
}
PyThreadState_Swap(wi->interpreter);
init_pyargv();
#ifdef UWSGI_EMBEDDED
// we need to inizialize an embedded module for every interpreter
init_uwsgi_embedded_module();
#endif
init_uwsgi_vars();
}
else {
wi->interpreter = up.main_thread;
}
wi->callable = up.loaders[loader](arg1);
if (!wi->callable) {
uwsgi_log("unable to load app SCRIPT_NAME=%s\n", mountpoint);
goto doh;
}
#ifdef UWSGI_ASYNC
wi->environ = malloc(sizeof(PyObject*)*uwsgi.cores);
if (!wi->environ) {
uwsgi_error("malloc()");
exit(1);
}
for(i=0;i<uwsgi.cores;i++) {
wi->environ[i] = PyDict_New();
if (!wi->environ[i]) {
uwsgi_log("unable to allocate new env dictionary for app\n");
exit(1);
}
}
#else
wi->environ = PyDict_New();
if (!wi->environ) {
uwsgi_log("unable to allocate new env dictionary for app\n");
exit(1);
}
#endif
// check function args
// by defaut it is a WSGI app
wi->argc = 2;
zero = PyObject_GetAttrString(wi->callable, "__code__");
if (!zero) {
zero = PyObject_GetAttrString(wi->callable, "__call__");
if (zero) {
zero = PyObject_GetAttrString(wi->callable, "__code__");
}
else {
uwsgi_log("WARNING: unable to get the number of callable args. Fallback to WSGI\n");
}
}
// avoid __code__ attr error propagation
PyErr_Clear();
if (zero) {
zero = PyObject_GetAttrString(zero, "co_argcount");
wi->argc = (int) PyInt_AsLong(zero);
}
if (wi->argc == 2) {
#ifdef UWSGI_DEBUG
uwsgi_log("-- WSGI callable detected --\n");
#endif
wi->request_subhandler = uwsgi_request_subhandler_wsgi;
wi->response_subhandler = uwsgi_response_subhandler_wsgi;
}
#ifdef UWSGI_WEB3
else if (wi->argc == 1) {
#ifdef UWSGI_DEBUG
uwsgi_log("-- Web3 callable detected --\n");
#endif
wi->request_subhandler = uwsgi_request_subhandler_web3;
wi->response_subhandler = uwsgi_response_subhandler_web3;
}
#endif
else {
uwsgi_log("-- INVALID callable detected --\n");
goto doh;
}
#ifdef UWSGI_ASYNC
wi->args = malloc(sizeof(PyObject*)*uwsgi.cores);
if (!wi->args) {
uwsgi_error("malloc()");
exit(1);
}
for(i=0;i<uwsgi.cores;i++) {
wi->args[i] = PyTuple_New(wi->argc);
if (!wi->args[i]) {
uwsgi_log("unable to allocate new tuple for app args\n");
exit(1);
}
// add start_response on WSGI app
if (wi->argc == 2) {
if (PyTuple_SetItem(wi->args[i], 1, up.wsgi_spitout)) {
uwsgi_log("unable to set start_response in args tuple\n");
exit(1);
}
}
}
#else
wi->wsgi_args = PyTuple_New(wi->argc);
if (wi->argc == 2) {
if (PyTuple_SetItem(wi->wsgi_args, 1, up.wsgi_spitout)) {
uwsgi_log("unable to set start_response in args tuple\n");
exit(1);
}
}
#endif
if (wi->argc == 2) {
#ifdef UWSGI_SENDFILE
// prepare sendfile() for WSGI app
wi->sendfile = PyCFunction_New(uwsgi_sendfile_method, NULL);
#endif
#ifdef UWSGI_ASYNC
wi->eventfd_read = PyCFunction_New(uwsgi_eventfd_read_method, NULL);
wi->eventfd_write = PyCFunction_New(uwsgi_eventfd_write_method, NULL);
#endif
}
if (new_interpreter && id) {
// if we have multiple threads we need to initialize a PyThreadState for each one
if (uwsgi.threads > 1) {
for(i=0;i<uwsgi.threads;i++) {
uwsgi.workers[uwsgi.mywid].cores[i]->ts[id] = PyThreadState_New( ((PyThreadState *)wi->interpreter)->interp);
if (!uwsgi.workers[uwsgi.mywid].cores[i]->ts[id]) {
uwsgi_log("unable to allocate new PyThreadState structure for app %s", mountpoint);
goto doh;
}
}
PyThreadState_Swap((PyThreadState *) pthread_getspecific(up.upt_save_key));
}
else {
PyThreadState_Swap(up.main_thread);
}
}
if (wi->argc == 1) {
uwsgi_log( "Web3 application %d (SCRIPT_NAME=%.*s) ready on interpreter %p", id, wi->mountpoint_len, wi->mountpoint, wi->interpreter);
}
else {
uwsgi_log( "WSGI application %d (SCRIPT_NAME=%.*s) ready on interpreter %p", id, wi->mountpoint_len, wi->mountpoint, wi->interpreter);
}
if (id == 0) {
uwsgi_log(" (default app)");
uwsgi.default_app = 0;
if (uwsgi.vhost) uwsgi.apps_cnt++;
}
else {
uwsgi.apps_cnt++;
}
uwsgi_log("\n");
return id;
doh:
free(mountpoint);
PyErr_Print();
if (new_interpreter && id) {
Py_EndInterpreter(wi->interpreter);
if (uwsgi.threads > 1) {
PyThreadState_Swap((PyThreadState *) pthread_getspecific(up.upt_save_key));
}
else {
PyThreadState_Swap(up.main_thread);
}
}
return -1;
}
char *get_uwsgi_pymodule(char *module) {
char *quick_callable;
if ( (quick_callable = strchr(module, ':')) ) {
quick_callable[0] = 0 ;
quick_callable++;
return quick_callable;
}
return NULL;
}
PyObject *get_uwsgi_pydict(char *module) {
PyObject *wsgi_module, *wsgi_dict;
wsgi_module = PyImport_ImportModule(module);
if (!wsgi_module) {
PyErr_Print();
return NULL;
}
wsgi_dict = PyModule_GetDict(wsgi_module);
if (!wsgi_dict) {
PyErr_Print();
return NULL;
}
return wsgi_dict;
}
PyObject *uwsgi_uwsgi_loader(void *arg1) {
PyObject *wsgi_dict;
char *quick_callable;
PyObject *tmp_callable;
char *module = (char *) arg1 ;
quick_callable = get_uwsgi_pymodule(module) ;
if (quick_callable == NULL) {
if (up.callable) {
quick_callable = up.callable ;
}
else {
quick_callable = "application";
}
}
wsgi_dict = get_uwsgi_pydict(module);
if (!wsgi_dict) {
return NULL;
}
// quick callable -> thanks gunicorn for the idea
// we have extended the concept a bit...
if (quick_callable[strlen(quick_callable) -2 ] == '(' && quick_callable[strlen(quick_callable) -1] ==')') {
quick_callable[strlen(quick_callable) -2 ] = 0 ;
tmp_callable = PyDict_GetItemString(wsgi_dict, quick_callable);
if (tmp_callable) {
return python_call(tmp_callable, PyTuple_New(0), 0);
}
}
return PyDict_GetItemString(wsgi_dict, quick_callable);
}
/* this is the mount loader, it loads app on mountpoint automagically */
PyObject *uwsgi_mount_loader(void *arg1) {
PyObject *callable = NULL ;
char *what = (char *) arg1;
if ( !strcmp(what+strlen(what)-3, ".py") || !strcmp(what+strlen(what)-3, ".wsgi")) {
callable = uwsgi_file_loader((void *)what);
}
#ifdef UWSGI_PASTE
else if (!strcmp(what+strlen(what)-4, ".ini")) {
callable = uwsgi_paste_loader((void *)what);
}
#endif
else {
callable = uwsgi_uwsgi_loader((void *)what);
}
return callable;
}
/* this is the dynamic loader, it loads app ireading nformation from a wsgi_request */
PyObject *uwsgi_dyn_loader(void *arg1) {
PyObject *callable = NULL ;
char *tmpstr;
struct wsgi_request *wsgi_req = (struct wsgi_request *) arg1;
// MANAGE UWSGI_SCRIPT
if (wsgi_req->wsgi_script_len > 0) {
tmpstr = uwsgi_strncopy(wsgi_req->wsgi_script, wsgi_req->wsgi_script_len);
callable = uwsgi_uwsgi_loader((void *)tmpstr);
free(tmpstr);
}
// MANAGE UWSGI_MODULE
else if (wsgi_req->wsgi_module_len > 0) {
if (wsgi_req->wsgi_callable_len > 0) {
tmpstr = uwsgi_concat3n(wsgi_req->wsgi_module, wsgi_req->wsgi_module_len, ":", 1, wsgi_req->wsgi_callable, wsgi_req->wsgi_callable_len);
}
else {
tmpstr = uwsgi_strncopy(wsgi_req->wsgi_module, wsgi_req->wsgi_module_len);
}
callable = uwsgi_uwsgi_loader((void *)tmpstr);
free(tmpstr);
}
// MANAGE UWSGI_FILE
else if (wsgi_req->wsgi_file_len > 0) {
tmpstr = uwsgi_strncopy(wsgi_req->wsgi_file, wsgi_req->wsgi_file_len);
callable = uwsgi_file_loader((void *)tmpstr);
free(tmpstr);
}
#ifdef UWSGI_PASTE
// MANAGE UWSGI_PASTE
else if (wsgi_req->wsgi_paste_len > 0) {
tmpstr = uwsgi_strncopy(wsgi_req->wsgi_paste, wsgi_req->wsgi_paste_len);
callable = uwsgi_paste_loader((void *)tmpstr);
free(tmpstr);
}
#endif
return callable;
}
/* trying to emulate Graham's mod_wsgi, this will allows easy and fast migrations */
PyObject *uwsgi_file_loader(void *arg1) {
char *filename = (char *) arg1;
FILE *wsgifile;
struct _node *wsgi_file_node = NULL;
PyObject *wsgi_compiled_node, *wsgi_file_module, *wsgi_file_dict;
PyObject *wsgi_file_callable;
wsgifile = fopen(filename, "r");
if (!wsgifile) {
uwsgi_error("fopen()");
exit(1);
}
wsgi_file_node = PyParser_SimpleParseFile(wsgifile, filename, Py_file_input);
if (!wsgi_file_node) {
PyErr_Print();
uwsgi_log( "failed to parse file %s\n", filename);
exit(1);
}
fclose(wsgifile);
wsgi_compiled_node = (PyObject *) PyNode_Compile(wsgi_file_node, filename);
if (!wsgi_compiled_node) {
PyErr_Print();
uwsgi_log( "failed to compile wsgi file %s\n", filename);
exit(1);
}
wsgi_file_module = PyImport_ExecCodeModule("uwsgi_wsgi_file", wsgi_compiled_node);
if (!wsgi_file_module) {
PyErr_Print();
exit(1);
}
Py_DECREF(wsgi_compiled_node);
wsgi_file_dict = PyModule_GetDict(wsgi_file_module);
if (!wsgi_file_dict) {
PyErr_Print();
exit(1);
}
wsgi_file_callable = PyDict_GetItemString(wsgi_file_dict, "application");
if (!wsgi_file_callable) {
PyErr_Print();
uwsgi_log( "unable to find \"application\" callable in file %s\n", filename);
exit(1);
}
if (!PyFunction_Check(wsgi_file_callable) && !PyCallable_Check(wsgi_file_callable)) {
uwsgi_log( "\"application\" must be a callable object in file %s\n", filename);
exit(1);
}
return wsgi_file_callable;
}
#ifdef UWSGI_PASTE
PyObject *uwsgi_paste_loader(void *arg1) {
char *paste = (char *) arg1;
PyObject *paste_module, *paste_dict, *paste_loadapp;
PyObject *paste_arg, *paste_app;
uwsgi_log( "Loading paste environment: %s\n", paste);
paste_module = PyImport_ImportModule("paste.deploy");
if (!paste_module) {
PyErr_Print();
exit(1);
}
paste_dict = PyModule_GetDict(paste_module);
if (!paste_dict) {
PyErr_Print();
exit(1);
}
paste_loadapp = PyDict_GetItemString(paste_dict, "loadapp");
if (!paste_loadapp) {
PyErr_Print();
exit(1);
}
paste_arg = PyTuple_New(1);
if (!paste_arg) {
PyErr_Print();
exit(1);
}
if (PyTuple_SetItem(paste_arg, 0, PyString_FromString(paste))) {
PyErr_Print();
exit(1);
}
paste_app = PyEval_CallObject(paste_loadapp, paste_arg);
if (!paste_app) {
PyErr_Print();
exit(1);
}
return paste_app;
}
#endif
PyObject *uwsgi_eval_loader(void *arg1) {
char *code = (char *) arg1;
PyObject *wsgi_eval_module, *wsgi_eval_callable = NULL;
struct _node *wsgi_eval_node = NULL;
PyObject *wsgi_compiled_node ;
wsgi_eval_node = PyParser_SimpleParseString(code, Py_file_input);
if (!wsgi_eval_node) {
PyErr_Print();
uwsgi_log( "failed to parse <eval> code\n");
exit(1);
}
wsgi_compiled_node = (PyObject *) PyNode_Compile(wsgi_eval_node, "uwsgi_eval_config");
if (!wsgi_compiled_node) {
PyErr_Print();
uwsgi_log( "failed to compile eval code\n");
exit(1);
}
wsgi_eval_module = PyImport_ExecCodeModule("uwsgi_eval_config", wsgi_compiled_node);
if (!wsgi_eval_module) {
PyErr_Print();
exit(1);
}
Py_DECREF(wsgi_compiled_node);
up.loader_dict = PyModule_GetDict(wsgi_eval_module);
if (!up.loader_dict) {
PyErr_Print();
exit(1);
}
if (up.callable) {
wsgi_eval_callable = PyDict_GetItemString(up.loader_dict, up.callable);
}
else {
wsgi_eval_callable = PyDict_GetItemString(up.loader_dict, "application");
}
if (wsgi_eval_callable) {
uwsgi_log( "found the \"%s\" callable\n", up.callable);
if (!PyFunction_Check(wsgi_eval_callable) && !PyCallable_Check(wsgi_eval_callable)) {
uwsgi_log( "you must define a callable object in your code\n");
exit(1);
}
}
return wsgi_eval_callable;
}
PyObject *uwsgi_callable_loader(void *arg1) {
return (PyObject *) arg1;
}
PyObject *uwsgi_string_callable_loader(void *arg1) {
char *callable = (char *) arg1;
return PyDict_GetItem(up.loader_dict, UWSGI_PYFROMSTRING(callable));
}
+614
View File
@@ -0,0 +1,614 @@
#include "uwsgi_python.h"
extern struct uwsgi_server uwsgi;
struct uwsgi_python up;
struct option uwsgi_python_options[] = {
{"wsgi-file", required_argument, 0, LONG_ARGS_WSGI_FILE},
{"file", required_argument, 0, LONG_ARGS_FILE_CONFIG},
{"eval", required_argument, 0, LONG_ARGS_EVAL_CONFIG},
{"module", required_argument, 0, 'w'},
{"callable", required_argument, 0, LONG_ARGS_CALLABLE},
{"test", required_argument, 0, 'j'},
{"home", required_argument, 0, 'H'},
{"pythonpath", required_argument, 0, LONG_ARGS_PYTHONPATH},
{"python-path", required_argument, 0, LONG_ARGS_PYTHONPATH},
{"pp", required_argument, 0, LONG_ARGS_PYTHONPATH},
{"pyargv", required_argument, 0, LONG_ARGS_PYARGV},
{"optimize", required_argument, 0, 'O'},
#ifdef UWSGI_PASTE
{"paste", required_argument, 0, LONG_ARGS_PASTE},
#ifdef UWSGI_INI
{"ini-paste", required_argument, 0, LONG_ARGS_INI_PASTE},
#endif
#endif
{"catch-exceptions", no_argument, &up.catch_exceptions, 1},
{"ignore-script-name", no_argument, &up.ignore_script_name, 1},
{"no-site", no_argument, &Py_NoSiteFlag, 1},
{0, 0, 0, 0},
};
/* this routine will be called after each fork to reinitialize the various locks */
void uwsgi_python_pthread_prepare(void) {
pthread_mutex_lock(&up.lock_pyloaders);
}
void uwsgi_python_pthread_parent(void) {
pthread_mutex_unlock(&up.lock_pyloaders);
}
void uwsgi_python_pthread_child(void) {
pthread_mutex_init(&up.lock_pyloaders, NULL);
}
// fake method
PyMethodDef null_methods[] = {
{ NULL, NULL},
};
PyMethodDef uwsgi_spit_method[] = { {"uwsgi_spit", py_uwsgi_spit, METH_VARARGS, ""} };
PyMethodDef uwsgi_write_method[] = { {"uwsgi_write", py_uwsgi_write, METH_VARARGS, ""} };
int uwsgi_python_init() {
uwsgi_log("Python version: %s\n", Py_GetVersion());
if (up.home != NULL) {
uwsgi_log("Setting PythonHome to %s...\n", up.home);
#ifdef PYTHREE
wchar_t *wpyhome;
wpyhome = malloc((sizeof(wchar_t) * strlen(up.home)) + 2);
if (!wpyhome) {
uwsgi_error("malloc()");
exit(1);
}
mbstowcs(wpyhome, up.home, strlen(up.home));
Py_SetPythonHome(wpyhome);
free(wpyhome);
#else
Py_SetPythonHome(up.home);
#endif
}
#ifdef PYTHREE
wchar_t pname[6];
mbstowcs(pname, "uWSGI", 6);
Py_SetProgramName(pname);
#else
Py_SetProgramName("uWSGI");
#endif
Py_Initialize();
Py_OptimizeFlag = up.optimize;
up.wsgi_spitout = PyCFunction_New(uwsgi_spit_method, NULL);
up.wsgi_writeout = PyCFunction_New(uwsgi_write_method, NULL);
up.main_thread = PyThreadState_Get();
if (up.test_module != NULL) {
if (PyImport_ImportModule(up.test_module)) {
exit(0);
}
exit(1);
}
init_uwsgi_vars();
// setup app loaders
#ifdef UWSGI_MINTERPRETERS
up.loaders[LOADER_DYN] = uwsgi_dyn_loader;
#endif
up.loaders[LOADER_UWSGI] = uwsgi_uwsgi_loader;
up.loaders[LOADER_FILE] = uwsgi_file_loader;
#ifdef UWSGI_PASTE
up.loaders[LOADER_PASTE] = uwsgi_paste_loader;
#endif
up.loaders[LOADER_EVAL] = uwsgi_eval_loader;
up.loaders[LOADER_MOUNT] = uwsgi_mount_loader;
up.loaders[LOADER_CALLABLE] = uwsgi_callable_loader;
up.loaders[LOADER_STRING_CALLABLE] = uwsgi_string_callable_loader;
// by default set a fake GIL (little impact on performance)
up.gil_get = gil_fake_get;
up.gil_release = gil_fake_release;
return 1;
}
void uwsgi_python_post_fork() {
PyObject *random_module, *random_dict, *random_seed;
// reinitialize the random seed (thanks Jonas Borgström)
random_module = PyImport_ImportModule("random");
if (random_module) {
random_dict = PyModule_GetDict(random_module);
if (random_dict) {
random_seed = PyDict_GetItemString(random_dict, "seed");
if (random_seed) {
PyObject *random_args = PyTuple_New(1);
// pass no args
PyTuple_SetItem(random_args, 0, Py_None);
PyEval_CallObject( random_seed, random_args );
if (PyErr_Occurred()) {
PyErr_Print();
}
}
}
}
#ifdef UWSGI_EMBEDDED
// call the post_fork_hook
PyObject *uwsgi_dict = get_uwsgi_pydict("uwsgi");
if (uwsgi_dict) {
PyObject *pfh = PyDict_GetItemString(uwsgi_dict, "post_fork_hook");
if (pfh) {
python_call(pfh, PyTuple_New(0), 0);
}
}
PyErr_Clear();
#endif
UWSGI_RELEASE_GIL
}
void init_uwsgi_vars() {
int i;
PyObject *pysys, *pysys_dict, *pypath;
#ifdef UWSGI_MINTERPRETERS
char venv_version[15] ;
PyObject *site_module;
#endif
/* add cwd to pythonpath */
pysys = PyImport_ImportModule("sys");
if (!pysys) {
PyErr_Print();
exit(1);
}
pysys_dict = PyModule_GetDict(pysys);
pypath = PyDict_GetItemString(pysys_dict, "path");
if (!pypath) {
PyErr_Print();
exit(1);
}
#ifdef UWSGI_MINTERPRETERS
// simulate a pythonhome directive
if (uwsgi.wsgi_req->pyhome_len > 0) {
PyObject *venv_path = UWSGI_PYFROMSTRINGSIZE(uwsgi.wsgi_req->pyhome, uwsgi.wsgi_req->pyhome_len) ;
#ifdef UWSGI_DEBUG
uwsgi_debug("setting dynamic virtualenv to %.*s\n", uwsgi.wsgi_req->pyhome_len, uwsgi.wsgi_req->pyhome);
#endif
PyDict_SetItemString(pysys_dict, "prefix", venv_path);
PyDict_SetItemString(pysys_dict, "exec_prefix", venv_path);
venv_version[14] = 0 ;
if (snprintf(venv_version, 15, "/lib/python%d.%d", PY_MAJOR_VERSION, PY_MINOR_VERSION) == -1) {
return ;
}
// check here
PyString_Concat( &venv_path, PyString_FromString(venv_version) );
if ( PyList_Insert(pypath, 0, venv_path) ) {
PyErr_Print();
}
site_module = PyImport_ImportModule("site");
if (site_module) {
PyImport_ReloadModule(site_module);
}
}
#endif
if (PyList_Insert(pypath, 0, UWSGI_PYFROMSTRING(".") ) != 0) {
PyErr_Print();
}
for (i = 0; i < up.python_path_cnt; i++) {
if (PyList_Insert(pypath, 0, UWSGI_PYFROMSTRING(up.python_path[i]) ) != 0) {
PyErr_Print();
}
else {
uwsgi_log( "added %s to pythonpath.\n", up.python_path[i]);
}
}
}
void uwsgi_uwsgi_config(char *module) {
#ifdef UWSGI_EMBEDDED
PyObject *uwsgi_module, *uwsgi_dict;
#endif
PyObject *applications;
PyObject *app_list;
Py_ssize_t i;
PyObject *app_mnt, *app_app = NULL;
char *quick_callable ;
quick_callable = get_uwsgi_pymodule(module);
if (quick_callable == NULL) {
if (up.callable) {
quick_callable = up.callable ;
}
else {
quick_callable = "application";
}
}
up.loader_dict = get_uwsgi_pydict(module);
if (!up.loader_dict) {
exit(1);
}
uwsgi_log( "...getting the applications list from the '%s' module...\n", module);
#ifdef UWSGI_EMBEDDED
uwsgi_module = PyImport_ImportModule("uwsgi");
if (!uwsgi_module) {
PyErr_Print();
exit(1);
}
uwsgi_dict = PyModule_GetDict(uwsgi_module);
if (!uwsgi_dict) {
PyErr_Print();
exit(1);
}
applications = PyDict_GetItemString(uwsgi_dict, "applications");
if (!PyDict_Check(applications)) {
uwsgi_log( "uwsgi.applications dictionary is not defined, trying with the \"applications\" one...\n");
#endif
applications = PyDict_GetItemString(up.loader_dict, "applications");
if (!applications) {
uwsgi_log( "applications dictionary is not defined, trying with the \"application\" callable.\n");
quick_callable = uwsgi_concat3(module, ":", quick_callable);
if (init_uwsgi_app(LOADER_UWSGI, (void *) quick_callable, uwsgi.wsgi_req, 0) < 0) {
uwsgi_log( "...goodbye cruel world...\n");
exit(1);
}
free(quick_callable);
return;
}
#ifdef UWSGI_EMBEDDED
}
#endif
if (!PyDict_Check(applications)) {
uwsgi_log( "The 'applications' object must be a dictionary.\n");
exit(1);
}
app_list = PyDict_Keys(applications);
if (!app_list) {
PyErr_Print();
exit(1);
}
if (PyList_Size(app_list) < 1) {
uwsgi_log( "You must define an app.\n");
exit(1);
}
for (i = 0; i < PyList_Size(app_list); i++) {
app_mnt = PyList_GetItem(app_list, i);
if (!PyString_Check(app_mnt)) {
uwsgi_log( "the app mountpoint must be a bytestring.\n");
exit(1);
}
uwsgi.wsgi_req->script_name = PyString_AsString(app_mnt);
uwsgi.wsgi_req->script_name_len = strlen(uwsgi.wsgi_req->script_name);
app_app = PyDict_GetItem(applications, app_mnt);
if (!PyString_Check(app_app) && !PyFunction_Check(app_app) && !PyCallable_Check(app_app)) {
uwsgi_log( "the app callable must be a string, a function or a callable. (found %s)\n", app_app->ob_type->tp_name);
exit(1);
}
#ifdef PYTHREE
if (PyUnicode_Check(app_app)) {
#else
if (PyString_Check(app_app)) {
#endif
if (init_uwsgi_app(LOADER_STRING_CALLABLE, (void *) PyString_AsString(app_app), uwsgi.wsgi_req, 0) < 0) {
uwsgi_log( "...goodbye cruel world...\n");
exit(1);
}
}
else {
if (init_uwsgi_app(LOADER_CALLABLE, (void *) app_app, uwsgi.wsgi_req, 0) < 0) {
uwsgi_log( "...goodbye cruel world...\n");
exit(1);
}
}
Py_DECREF(app_mnt);
Py_DECREF(app_app);
}
}
#ifdef PYTHREE
static PyModuleDef uwsgi_module3 = {
PyModuleDef_HEAD_INIT,
"uwsgi",
NULL,
-1,
null_methods,
};
PyObject *init_uwsgi3(void) {
return PyModule_Create(&uwsgi_module3);
}
#endif
#ifdef UWSGI_EMBEDDED
void init_uwsgi_embedded_module() {
PyObject *new_uwsgi_module, *zero;
int i;
/* initialize for stats */
uwsgi.workers_tuple = PyTuple_New(uwsgi.numproc);
for (i = 0; i < uwsgi.numproc; i++) {
zero = PyDict_New();
Py_INCREF(zero);
PyTuple_SetItem(uwsgi.workers_tuple, i, zero);
}
#ifdef PYTHREE
PyImport_AppendInittab("uwsgi", init_uwsgi3);
new_uwsgi_module = PyImport_AddModule("uwsgi");
#else
new_uwsgi_module = Py_InitModule("uwsgi", null_methods);
#endif
if (new_uwsgi_module == NULL) {
uwsgi_log( "could not initialize the uwsgi python module\n");
exit(1);
}
uwsgi.embedded_dict = PyModule_GetDict(new_uwsgi_module);
if (!uwsgi.embedded_dict) {
uwsgi_log( "could not get uwsgi module __dict__\n");
exit(1);
}
if (PyDict_SetItemString(uwsgi.embedded_dict, "version", PyString_FromString(UWSGI_VERSION))) {
PyErr_Print();
exit(1);
}
if (uwsgi.mode) {
if (PyDict_SetItemString(uwsgi.embedded_dict, "mode", PyString_FromString(uwsgi.mode))) {
PyErr_Print();
exit(1);
}
}
if (uwsgi.pidfile) {
if (PyDict_SetItemString(uwsgi.embedded_dict, "pidfile", PyString_FromString(uwsgi.pidfile))) {
PyErr_Print();
exit(1);
}
}
if (PyDict_SetItemString(uwsgi.embedded_dict, "SPOOL_RETRY", PyInt_FromLong(17))) {
PyErr_Print();
exit(1);
}
if (PyDict_SetItemString(uwsgi.embedded_dict, "numproc", PyInt_FromLong(uwsgi.numproc))) {
PyErr_Print();
exit(1);
}
#ifdef UNBIT
if (PyDict_SetItemString(uwsgi.embedded_dict, "unbit", Py_True)) {
#else
if (PyDict_SetItemString(uwsgi.embedded_dict, "unbit", Py_None)) {
#endif
PyErr_Print();
exit(1);
}
if (PyDict_SetItemString(uwsgi.embedded_dict, "buffer_size", PyInt_FromLong(uwsgi.buffer_size))) {
PyErr_Print();
exit(1);
}
if (PyDict_SetItemString(uwsgi.embedded_dict, "started_on", PyInt_FromLong(uwsgi.start_tv.tv_sec))) {
PyErr_Print();
exit(1);
}
if (PyDict_SetItemString(uwsgi.embedded_dict, "start_response", up.wsgi_spitout)) {
PyErr_Print();
exit(1);
}
if (PyDict_SetItemString(uwsgi.embedded_dict, "fastfuncs", PyList_New(256))) {
PyErr_Print();
exit(1);
}
if (PyDict_SetItemString(uwsgi.embedded_dict, "applications", Py_None)) {
PyErr_Print();
exit(1);
}
if (uwsgi.is_a_reload) {
if (PyDict_SetItemString(uwsgi.embedded_dict, "is_a_reload", Py_True)) {
PyErr_Print();
exit(1);
}
}
else {
if (PyDict_SetItemString(uwsgi.embedded_dict, "is_a_reload", Py_False)) {
PyErr_Print();
exit(1);
}
}
uwsgi.embedded_args = PyTuple_New(2);
if (!uwsgi.embedded_args) {
PyErr_Print();
exit(1);
}
if (PyDict_SetItemString(uwsgi.embedded_dict, "message_manager_marshal", Py_None)) {
PyErr_Print();
exit(1);
}
uwsgi.fastfuncslist = PyDict_GetItemString(uwsgi.embedded_dict, "fastfuncs");
if (!uwsgi.fastfuncslist) {
PyErr_Print();
exit(1);
}
init_uwsgi_module_advanced(new_uwsgi_module);
#ifdef UWSGI_SPOOLER
if (uwsgi.spool_dir != NULL) {
init_uwsgi_module_spooler(new_uwsgi_module);
}
#endif
if (uwsgi.sharedareasize > 0 && uwsgi.sharedarea) {
init_uwsgi_module_sharedarea(new_uwsgi_module);
}
}
#endif
int uwsgi_python_manage_options(int i, char *optarg) {
switch(i) {
case 'w':
up.wsgi_config = optarg;
return 1;
case LONG_ARGS_PYTHONPATH:
uwsgi_log("found PYTHONPATH\n");
if (up.python_path_cnt < MAX_PYTHONPATH) {
up.python_path[up.python_path_cnt] = optarg;
up.python_path_cnt++;
}
else {
uwsgi_log( "you can specify at most %d --pythonpath options\n", MAX_PYTHONPATH);
}
return 1;
case LONG_ARGS_PYARGV:
up.argv = optarg;
return 1;
case 'j':
up.test_module = optarg;
return 1;
case 'H':
up.home = optarg;
return 1;
case LONG_ARGS_CALLABLE:
up.callable = optarg;
return 1;
}
return 0;
}
void uwsgi_python_init_app() {
if (up.wsgi_config != NULL) {
init_uwsgi_app(LOADER_UWSGI, up.wsgi_config, uwsgi.wsgi_req, 0);
}
if (up.file_config != NULL) {
init_uwsgi_app(LOADER_FILE, up.file_config, uwsgi.wsgi_req, 0);
}
#ifdef UWSGI_PASTE
if (up.paste != NULL) {
init_uwsgi_app(LOADER_PASTE, up.paste, uwsgi.wsgi_req, 0);
}
#endif
if (up.eval != NULL) {
init_uwsgi_app(LOADER_EVAL, up.eval, uwsgi.wsgi_req, 0);
}
}
void uwsgi_python_enable_threads() {
PyEval_InitThreads();
if (pthread_key_create(&up.upt_save_key, NULL)) {
uwsgi_error("pthread_key_create()");
exit(1);
}
pthread_setspecific(up.upt_save_key, (void *) PyThreadState_Get());
pthread_mutex_init(&up.lock_pyloaders, NULL);
pthread_atfork(uwsgi_python_pthread_prepare, uwsgi_python_pthread_parent, uwsgi_python_pthread_child);
up.gil_get = gil_real_get;
up.gil_release = gil_real_release;
uwsgi_log("threads support enabled\n");
}
void uwsgi_python_init_thread() {
// set a new ThreadState for each thread
PyThreadState *pts;
pts = PyThreadState_New(up.main_thread->interp);
pthread_setspecific(up.upt_save_key, (void *) pts);
}
struct uwsgi_plugin python_plugin = {
.name = "python",
.modifier1 = 0,
.init = uwsgi_python_init,
.post_fork = uwsgi_python_post_fork,
.options = uwsgi_python_options,
.manage_opt = uwsgi_python_manage_options,
.request = uwsgi_request_wsgi,
.after_request = uwsgi_after_request_wsgi,
.init_apps = uwsgi_python_init_app,
.enable_threads = uwsgi_python_enable_threads,
.init_thread = uwsgi_python_init_thread,
/*
.magic = uwsgi_python_magic,
.help = uwsgi_python_help,
*/
};
+100
View File
@@ -0,0 +1,100 @@
#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);
}
PyObject *python_call(PyObject *callable, PyObject *args, int catch) {
PyObject *pyret;
uwsgi_log("CALLING %p %p\n", callable, args);
pyret = PyEval_CallObject(callable, args);
uwsgi_log("CALLED\n");
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
uwsgi_log("called\n");
return pyret;
}
int uwsgi_python_call(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(wsgi_req) != UWSGI_OK) {
#ifdef UWSGI_ASYNC
if (uwsgi.async > 1) {
return UWSGI_AGAIN;
}
#endif
}
}
return UWSGI_OK;
}
void init_pyargv() {
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 (up.argv != NULL && !up.argc) {
up.argc++;
#ifdef PYTHREE
wchar_t *wcargv = malloc( sizeof( wchar_t ) * (strlen(up.argv)+1));
if (!wcargv) {
uwsgi_error("malloc()");
exit(1);
}
memset(wcargv, 0, sizeof( wchar_t ) * (strlen(up.argv)+1));
#endif
#ifdef __sun__
// FIX THIS !!!
ap = strtok(up.argv, " ");
while ((ap = strtok(NULL, " ")) != NULL) {
#else
while ((ap = strsep(&up.argv, " \t")) != NULL) {
#endif
if (*ap != '\0') {
#ifdef PYTHREE
mbstowcs( wcargv + strlen(ap), ap, strlen(ap));
uwsgi.py_argv[up.argc] = wcargv + strlen(ap);
#else
uwsgi.py_argv[up.argc] = ap;
#endif
up.argc++;
}
if (up.argc + 1 > MAX_PYARGV)
break;
}
}
PySys_SetArgv(up.argc, &up.argv);
}
+169
View File
@@ -0,0 +1,169 @@
#include "../../uwsgi.h"
#include <Python.h>
#define MAX_PYTHONPATH 64
#ifdef UWSGI_STACKLESS
#include <stackless_api.h>
#endif
#if PY_MINOR_VERSION == 4 && PY_MAJOR_VERSION == 2
#define Py_ssize_t ssize_t
#endif
#if PY_MAJOR_VERSION > 2
#define PYTHREE
#endif
#ifdef UWSGI_THREADING
#define UWSGI_GET_GIL (*up.gil_get)();
#define UWSGI_RELEASE_GIL (*up.gil_release)();
#else
#define UWSGI_GET_GIL
#define UWSGI_RELEASE_GIL
#endif
PyAPI_FUNC(PyObject *) PyMarshal_WriteObjectToString(PyObject *, int);
PyAPI_FUNC(PyObject *) PyMarshal_ReadObjectFromString(char *, Py_ssize_t);
#ifdef PYTHREE
#define UWSGI_PYFROMSTRING(x) PyUnicode_FromString(x)
#define UWSGI_PYFROMSTRINGSIZE(x, y) PyUnicode_FromStringAndSize(x, y)
#define PyInt_FromLong PyLong_FromLong
#define PyInt_AsLong PyLong_AsLong
#define PyInt_Check PyLong_Check
#define PyString_Check PyBytes_Check
#define PyString_FromStringAndSize PyBytes_FromStringAndSize
#define PyString_FromFormat PyBytes_FromFormat
#define PyString_FromString PyBytes_FromString
#define PyString_Size PyBytes_Size
#define PyString_Concat PyBytes_Concat
#define PyString_AsString (char *) PyBytes_AsString
#define PyFile_FromFile(A,B,C,D) PyFile_FromFd(fileno((A)), (B), (C), -1, NULL, NULL, NULL, 0)
#else
#define UWSGI_PYFROMSTRING(x) PyString_FromString(x)
#define UWSGI_PYFROMSTRINGSIZE(x, y) PyString_FromStringAndSize(x, y)
#endif
struct uwsgi_python {
char *home;
int optimize;
char *argv;
int argc;
PyObject *wsgi_spitout;
PyObject *wsgi_writeout;
PyThreadState *main_thread;
char *test_module;
char *python_path[MAX_PYTHONPATH];
int python_path_cnt;
PyObject *loader_dict;
PyObject* (*loaders[LOADER_MAX]) (void *);
char *wsgi_config;
char *file_config;
char *paste;
char *eval;
char *callable;
int ignore_script_name;
int catch_exceptions;
#ifdef UWSGI_THREADING
pthread_key_t upt_save_key;
pthread_mutex_t lock_pyloaders;
void (*gil_get) (void);
void (*gil_release) (void);
#endif
};
void init_uwsgi_vars(void);
void init_uwsgi_embedded_module(void);
void uwsgi_wsgi_config(char *);
#ifdef UWSGI_PASTE
void uwsgi_paste_config(char *);
#endif
void uwsgi_file_config(char *);
void uwsgi_eval_config(char *);
int init_uwsgi_app(int, void *, struct wsgi_request *wsgi_req, int);
PyObject *py_eventfd_read(PyObject *, PyObject *) ;
PyObject *py_eventfd_write(PyObject *, PyObject *) ;
#ifdef UWSGI_STACKLESS
PyObject *py_uwsgi_stackless(PyObject *, PyObject *) ;
#endif
int manage_python_response(struct wsgi_request *);
int uwsgi_python_call(struct wsgi_request *, PyObject *, PyObject *);
PyObject *python_call(PyObject *, PyObject *, int);
#ifdef UWSGI_SENDFILE
PyObject *py_uwsgi_sendfile(PyObject *, PyObject *) ;
ssize_t uwsgi_sendfile(struct wsgi_request *);
ssize_t uwsgi_do_sendfile(int, int, size_t, size_t, off_t*, int);
#endif
PyObject *py_uwsgi_write(PyObject *, PyObject *) ;
PyObject *py_uwsgi_spit(PyObject *, PyObject *) ;
#ifdef UWSGI_STACKLESS
struct stackless_req {
PyTaskletObject *tasklet;
struct wsgi_request *wsgi_req;
PyChannelObject *channel;
};
struct wsgi_request *find_request_by_tasklet(PyTaskletObject *);
void stackless_init(void);
void stackless_loop(void);
#endif
void init_pyargv(void);
#ifdef UWSGI_WEB3
void *uwsgi_request_subhandler_web3(struct wsgi_request *, struct uwsgi_app *);
int uwsgi_response_subhandler_web3(struct wsgi_request *);
#endif
PyObject *uwsgi_uwsgi_loader(void *);
PyObject *uwsgi_dyn_loader(void *);
PyObject *uwsgi_file_loader(void *);
PyObject *uwsgi_eval_loader(void *);
PyObject *uwsgi_paste_loader(void *);
PyObject *uwsgi_callable_loader(void *);
PyObject *uwsgi_string_callable_loader(void *);
PyObject *uwsgi_mount_loader(void *);
char *get_uwsgi_pymodule(char *);
PyObject *get_uwsgi_pydict(char *);
int uwsgi_request_wsgi(struct wsgi_request *);
void uwsgi_after_request_wsgi(struct wsgi_request *);
void *uwsgi_request_subhandler_wsgi(struct wsgi_request *, struct uwsgi_app*);
int uwsgi_response_subhandler_wsgi(struct wsgi_request *);
void gil_real_get(void);
void gil_real_release(void);
void gil_fake_get(void);
void gil_fake_release(void);
+22
View File
@@ -0,0 +1,22 @@
import os,sys
from distutils import sysconfig
NAME='python'
GCC_LIST = ['python_plugin', 'pyutils', 'pyloader', 'wsgi_handlers', 'wsgi_headers', 'wsgi_subhandler', 'gil']
CFLAGS = ['-I' + sysconfig.get_python_inc(), '-I' + sysconfig.get_python_inc(plat_specific=True) ]
LDFLAGS = []
LIBS = sysconfig.get_config_var('LIBS').split() + sysconfig.get_config_var('SYSLIBS').split()
if not sysconfig.get_config_var('Py_ENABLE_SHARED'):
LIBS.append('-L' + sysconfig.get_config_var('LIBPL'))
version = sys.version_info
uver = "%d.%d" % (version[0], version[1])
LIBS.append('-lpython' + uver)
#if str(PYLIB_PATH) != '':
# libs.insert(0,'-L' + PYLIB_PATH)
# os.environ['LD_RUN_PATH'] = PYLIB_PATH
Binary file not shown.
+165
View File
@@ -0,0 +1,165 @@
#include "uwsgi.h"
extern struct uwsgi_server uwsgi;
void *uwsgi_request_subhandler_web3(struct wsgi_request *wsgi_req, struct uwsgi_app *wi) {
PyObject *zero, *wsgi_socket;
wsgi_socket = PyFile_FromFile(wsgi_req->async_post, "web3_input", "r", NULL);
PyDict_SetItemString(wsgi_req->async_environ, "web3.input", wsgi_socket);
Py_DECREF(wsgi_socket);
zero = PyTuple_New(2);
PyTuple_SetItem(zero, 0, PyInt_FromLong(1));
PyTuple_SetItem(zero, 1, PyInt_FromLong(0));
PyDict_SetItemString(wsgi_req->async_environ, "web3.version", zero);
Py_DECREF(zero);
zero = PyFile_FromFile(stderr, "web3_input", "w", NULL);
PyDict_SetItemString(wsgi_req->async_environ, "web3.errors", zero);
Py_DECREF(zero);
PyDict_SetItemString(wsgi_req->async_environ, "web3.run_once", Py_False);
PyDict_SetItemString(wsgi_req->async_environ, "web3.multithread", Py_False);
if (uwsgi.numproc == 1) {
PyDict_SetItemString(wsgi_req->async_environ, "web3.multiprocess", Py_False);
}
else {
PyDict_SetItemString(wsgi_req->async_environ, "web3.multiprocess", Py_True);
}
if (wsgi_req->scheme_len > 0) {
zero = PyString_FromStringAndSize(wsgi_req->scheme, wsgi_req->scheme_len);
}
else if (wsgi_req->https_len > 0) {
if (!strncasecmp(wsgi_req->https, "on", 2) || wsgi_req->https[0] == '1') {
zero = PyString_FromString("https");
}
else {
zero = PyString_FromString("http");
}
}
else {
zero = PyString_FromString("http");
}
PyDict_SetItemString(wsgi_req->async_environ, "web3.url_scheme", zero);
Py_DECREF(zero);
wsgi_req->async_app = wi->wsgi_callable ;
PyDict_SetItemString(uwsgi.embedded_dict, "env", wsgi_req->async_environ);
// TODO: fix this
//PyDict_SetItemString(wsgi_req->async_environ, "uwsgi.version", uwsgi_version);
// call
PyTuple_SetItem(wsgi_req->async_args, 0, wsgi_req->async_environ);
return python_call(wsgi_req->async_app, wsgi_req->async_args, uwsgi.catch_exceptions);
}
int uwsgi_response_subhandler_web3(struct wsgi_request *wsgi_req) {
PyObject *pychunk ;
ssize_t wsize ;
// return or yield ? (PyString on python2 PyBytes on python3)
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;
}
// ok its a yield
if (!wsgi_req->async_placeholder) {
if (PyTuple_Check((PyObject *)wsgi_req->async_result)) {
if (PyTuple_Size((PyObject *)wsgi_req->async_result) != 3) {
uwsgi_log("invalid Web3 response.\n");
goto clear;
}
if (py_uwsgi_spit(NULL, (PyObject *)wsgi_req->async_result) == Py_None) {
goto clear;
}
wsgi_req->async_result = PyTuple_GetItem((PyObject *)wsgi_req->async_result, 0);
wsgi_req->async_placeholder = PyObject_GetIter( (PyObject *)wsgi_req->async_result );
if (!wsgi_req->async_placeholder) {
goto clear2;
}
#ifdef UWSGI_ASYNC
if (uwsgi.async > 1) {
return UWSGI_AGAIN;
}
}
else {
uwsgi_log("invalid Web3 response.\n");
goto clear;
}
#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;
}
Py_DECREF(pychunk);
return UWSGI_AGAIN ;
clear:
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);
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);
}
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;
}
+451
View File
@@ -0,0 +1,451 @@
#include "uwsgi_python.h"
extern struct uwsgi_server uwsgi;
extern struct uwsgi_python up;
PyObject *py_uwsgi_write(PyObject * self, PyObject * args) {
PyObject *data;
char *content;
int len;
struct wsgi_request *wsgi_req = current_wsgi_req();
data = PyTuple_GetItem(args, 0);
if (PyString_Check(data)) {
content = PyString_AsString(data);
len = PyString_Size(data);
UWSGI_RELEASE_GIL
wsgi_req->response_size = write(wsgi_req->poll.fd, content, len);
UWSGI_GET_GIL
}
Py_INCREF(Py_None);
return Py_None;
}
#ifdef UWSGI_ASYNC
PyObject *py_eventfd_read(PyObject * self, PyObject * args) {
int fd, timeout;
struct wsgi_request *wsgi_req = current_wsgi_req();
if (!PyArg_ParseTuple(args, "i|i", &fd, &timeout)) {
return NULL;
}
if (fd >= 0) {
wsgi_req->async_waiting_fd = fd ;
wsgi_req->async_waiting_fd_type = ASYNC_IN ;
wsgi_req->async_waiting_fd_monitored = 0 ;
}
return PyString_FromString("") ;
}
PyObject *py_eventfd_write(PyObject * self, PyObject * args) {
int fd, timeout;
struct wsgi_request *wsgi_req = current_wsgi_req();
if (!PyArg_ParseTuple(args, "i|i", &fd, &timeout)) {
return NULL;
}
if (fd >= 0) {
wsgi_req->async_waiting_fd = fd ;
wsgi_req->async_waiting_fd_type = ASYNC_OUT ;
wsgi_req->async_waiting_fd_monitored = 0 ;
}
return PyString_FromString("") ;
}
#endif
int uwsgi_request_wsgi(struct wsgi_request *wsgi_req) {
int i;
size_t post_remains = wsgi_req->post_cl;
ssize_t post_chunk;
PyObject *pydictkey, *pydictvalue;
char *path_info;
struct uwsgi_app *wi ;
int tmp_stderr;
char *what;
int what_len;
#ifdef UWSGI_ASYNC
if (wsgi_req->async_status == UWSGI_AGAIN) {
// get rid of timeout
if (wsgi_req->async_timeout_expired) {
PyDict_SetItemString(wsgi_req->async_environ, "x-wsgiorg.fdevent.timeout", Py_True);
wsgi_req->async_timeout_expired = 0 ;
}
else {
PyDict_SetItemString(wsgi_req->async_environ, "x-wsgiorg.fdevent.timeout", Py_None);
}
return manage_python_response(wsgi_req);
}
#endif
/* Standard WSGI request */
if (!wsgi_req->uh.pktsize) {
uwsgi_log( "Invalid WSGI request. skip.\n");
return -1;
}
if (uwsgi_parse_vars(wsgi_req)) {
uwsgi_log("Invalid WSGI request. skip.\n");
return -1;
}
uwsgi_log("uno\n");
if (uwsgi.limit_post) {
if (wsgi_req->post_cl > uwsgi.limit_post) {
uwsgi_log("Invalid (too big) CONTENT_LENGTH. skip.\n");
return -1;
}
}
if (!up.ignore_script_name) {
if (!wsgi_req->script_name)
wsgi_req->script_name = "";
if (uwsgi.vhost) {
what = uwsgi_concat3n(wsgi_req->host, wsgi_req->host_len, "|",1, wsgi_req->script_name, wsgi_req->script_name_len);
what_len = wsgi_req->host_len + 1 + wsgi_req->script_name_len ;
#ifdef UWSGI_DEBUG
uwsgi_debug("VirtualHost SCRIPT_NAME=%s\n", what);
#endif
}
else {
what = wsgi_req->script_name;
what_len = wsgi_req->script_name_len ;
}
if ( (wsgi_req->app_id = uwsgi_get_app_id(what, what_len)) == -1) {
if (wsgi_req->script_name_len > 1 || uwsgi.default_app < 0 || uwsgi.vhost) {
/* unavailable app for this SCRIPT_NAME */
wsgi_req->app_id = -1;
if (wsgi_req->wsgi_script_len > 0
|| wsgi_req->wsgi_module_len > 0
|| wsgi_req->wsgi_file_len > 0
#ifdef UWSGI_PASTE
|| wsgi_req->wsgi_paste_len > 0
#endif
) {
// a bit of magic: 1-1 = 0 / 0-1 = -1
// this part must be heavy locked in threaded modes
if (uwsgi.threads > 1) {
pthread_mutex_lock(&up.lock_pyloaders);
}
UWSGI_GET_GIL
wsgi_req->app_id = init_uwsgi_app(LOADER_DYN, (void *) wsgi_req, wsgi_req, uwsgi.single_interpreter-1);
UWSGI_RELEASE_GIL
if (uwsgi.threads > 1) {
pthread_mutex_unlock(&up.lock_pyloaders);
}
}
}
}
if (uwsgi.vhost) {
free(what);
}
}
else {
wsgi_req->app_id = 0;
}
if (wsgi_req->app_id == -1) {
// use default app ?
if (!uwsgi.no_default_app && uwsgi.default_app >= 0) {
wsgi_req->app_id = uwsgi.default_app ;
}
else {
internal_server_error(wsgi_req->poll.fd, "wsgi application not found");
goto clear2;
}
}
wi = &uwsgi.apps[wsgi_req->app_id];
if (uwsgi.single_interpreter == 0 && wsgi_req->app_id > 0) {
if (!wi->interpreter) {
internal_server_error(wsgi_req->poll.fd, "wsgi application's %d interpreter not found");
goto clear2;
}
// set the interpreter
UWSGI_GET_GIL
if (uwsgi.threads > 1) {
PyThreadState_Swap(uwsgi.workers[uwsgi.mywid].cores[wsgi_req->async_id]->ts[wsgi_req->app_id]);
}
else {
PyThreadState_Swap(wi->interpreter);
}
UWSGI_RELEASE_GIL
if (wi->chdir) {
#ifdef UWSGI_DEBUG
uwsgi_debug("chdir to %s\n", wi->chdir);
#endif
if (chdir(wi->chdir)) {
uwsgi_error("chdir()");
}
}
}
if (wsgi_req->protocol_len < 5) {
uwsgi_log( "INVALID PROTOCOL: %.*s\n", wsgi_req->protocol_len, wsgi_req->protocol);
internal_server_error(wsgi_req->poll.fd, "invalid HTTP protocol !!!");
goto clear;
}
if (strncmp(wsgi_req->protocol, "HTTP/", 5)) {
uwsgi_log( "INVALID PROTOCOL: %.*s\n", wsgi_req->protocol_len, wsgi_req->protocol);
internal_server_error(wsgi_req->poll.fd, "invalid HTTP protocol !!!");
goto clear;
}
#ifdef UWSGI_ASYNC
wsgi_req->async_environ = wi->environ[wsgi_req->async_id];
wsgi_req->async_args = wi->args[wsgi_req->async_id];
#else
wsgi_req->async_environ = wi->environ;
wsgi_req->async_args = wi->args;
#endif
UWSGI_GET_GIL
// no fear of race conditions for this counter as it is already protected by the GIL
wi->requests++;
Py_INCREF((PyObject *)wsgi_req->async_environ);
for (i = 0; i < wsgi_req->var_cnt; i += 2) {
#ifdef UWSGI_DEBUG
uwsgi_debug("%.*s: %.*s\n", wsgi_req->hvec[i].iov_len, wsgi_req->hvec[i].iov_base, wsgi_req->hvec[i+1].iov_len, wsgi_req->hvec[i+1].iov_base);
#endif
#ifdef PYTHREE
pydictkey = PyUnicode_DecodeLatin1(wsgi_req->hvec[i].iov_base, wsgi_req->hvec[i].iov_len, "ignore");
pydictvalue = PyUnicode_DecodeLatin1(wsgi_req->hvec[i + 1].iov_base, wsgi_req->hvec[i + 1].iov_len, "ignore");
#else
pydictkey = PyString_FromStringAndSize(wsgi_req->hvec[i].iov_base, wsgi_req->hvec[i].iov_len);
pydictvalue = PyString_FromStringAndSize(wsgi_req->hvec[i + 1].iov_base, wsgi_req->hvec[i + 1].iov_len);
#endif
PyDict_SetItem(wsgi_req->async_environ, pydictkey, pydictvalue);
Py_DECREF(pydictkey);
Py_DECREF(pydictvalue);
}
if (wsgi_req->uh.modifier1 == UWSGI_MODIFIER_MANAGE_PATH_INFO) {
pydictkey = PyDict_GetItemString(wsgi_req->async_environ, "SCRIPT_NAME");
if (pydictkey) {
if (PyString_Check(pydictkey)) {
pydictvalue = PyDict_GetItemString(wsgi_req->async_environ, "PATH_INFO");
if (pydictvalue) {
if (PyString_Check(pydictvalue)) {
path_info = PyString_AsString(pydictvalue);
PyDict_SetItemString(wsgi_req->async_environ, "PATH_INFO", PyString_FromString(path_info + PyString_Size(pydictkey)));
}
}
}
}
}
uwsgi_log("OOOOOPS000\n");
if (uwsgi.post_buffering > 0 && wsgi_req->post_cl > (size_t) uwsgi.post_buffering) {
UWSGI_RELEASE_GIL
wsgi_req->async_post = tmpfile();
if (!wsgi_req->async_post) {
uwsgi_error("tmpfile()");
goto clear;
}
while(post_remains > 0) {
if (uwsgi.shared->options[UWSGI_OPTION_HARAKIRI] > 0) {
inc_harakiri(uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
}
if (post_remains > (size_t) uwsgi.post_buffering_bufsize) {
post_chunk = read(wsgi_req->poll.fd, wsgi_req->post_buffering_buf, uwsgi.post_buffering_bufsize);
}
else {
post_chunk = read(wsgi_req->poll.fd, wsgi_req->post_buffering_buf, post_remains);
}
if (post_chunk < 0) {
uwsgi_error("read()");
goto clear;
}
if (!fwrite(wsgi_req->post_buffering_buf, post_chunk, 1, wsgi_req->async_post)) {
uwsgi_error("fwrite()");
goto clear;
}
post_remains -= post_chunk;
}
rewind(wsgi_req->async_post);
UWSGI_GET_GIL
}
else {
wsgi_req->async_post = fdopen(wsgi_req->poll.fd, "r");
}
wsgi_req->async_result = wi->request_subhandler(wsgi_req, wi);
uwsgi_log("fase2\n");
if (wsgi_req->async_result) {
UWSGI_RELEASE_GIL
while ( (*wi->response_subhandler)(wsgi_req) != UWSGI_OK) {
wsgi_req->switches++;
uwsgi_log("again...\n");
#ifdef UWSGI_ASYNC
if (uwsgi.async > 1) {
return UWSGI_AGAIN;
}
#endif
}
}
else if (up.catch_exceptions) {
// LOCK THIS PART
wsgi_req->response_size += write(wsgi_req->poll.fd, wsgi_req->protocol, wsgi_req->protocol_len);
wsgi_req->response_size += write(wsgi_req->poll.fd, " 500 Internal Server Error\r\n", 28 );
wsgi_req->response_size += write(wsgi_req->poll.fd, "Content-type: text/plain\r\n\r\n", 28 );
wsgi_req->header_cnt = 1 ;
/*
sorry that is a hack to avoid the rewrite of PyErr_Print
temporarily map (using dup2) stderr to wsgi_req->poll.fd
*/
tmp_stderr = dup(2);
if (tmp_stderr < 0) {
uwsgi_error("dup()");
goto clear;
}
// map 2 to wsgi_req
if (dup2(wsgi_req->poll.fd, 2) < 0) {
close(tmp_stderr);
uwsgi_error("dup2()");
goto clear;
}
// print the error
PyErr_Print();
// ...resume the original stderr, in case of error we are damaged forever !!!
if (dup2(tmp_stderr, 2) < 0) {
uwsgi_error("dup2()");
}
close(tmp_stderr);
}
uwsgi_log("opps\n");
clear:
UWSGI_GET_GIL
if (uwsgi.single_interpreter == 0 && wsgi_req->app_id > 0) {
// restoring main interpreter
if (uwsgi.threads > 1) {
PyThreadState_Swap((PyThreadState *) pthread_getspecific(up.upt_save_key));
}
else {
PyThreadState_Swap(up.main_thread);
}
}
UWSGI_RELEASE_GIL
clear2:
return UWSGI_OK;
}
void uwsgi_after_request_wsgi(struct wsgi_request *wsgi_req) {
uwsgi_log("LOGGING\n");
if (uwsgi.shared->options[UWSGI_OPTION_LOGGING]) {
log_request(wsgi_req);
}
else {
if (uwsgi.shared->options[UWSGI_OPTION_LOG_ZERO]) {
if (wsgi_req->response_size == 0) { log_request(wsgi_req); return; }
}
if (uwsgi.shared->options[UWSGI_OPTION_LOG_SLOW]) {
if ((uint32_t) wsgi_req_time >= uwsgi.shared->options[UWSGI_OPTION_LOG_SLOW]) { log_request(wsgi_req); return; }
}
if (uwsgi.shared->options[UWSGI_OPTION_LOG_4xx]) {
if (wsgi_req->status >= 400 && wsgi_req->status <= 499) { log_request(wsgi_req); return; }
}
if (uwsgi.shared->options[UWSGI_OPTION_LOG_5xx]) {
if (wsgi_req->status >= 500 && wsgi_req->status <= 599) { log_request(wsgi_req); return; }
}
if (uwsgi.shared->options[UWSGI_OPTION_LOG_BIG]) {
if (wsgi_req->response_size >= uwsgi.shared->options[UWSGI_OPTION_LOG_BIG]) { log_request(wsgi_req); return; }
}
if (uwsgi.shared->options[UWSGI_OPTION_LOG_SENDFILE]) {
if (wsgi_req->sendfile_fd > -1 && wsgi_req->sendfile_obj == wsgi_req->async_result) { log_request(wsgi_req); return; }
}
}
}
#ifdef UWSGI_SENDFILE
PyObject *py_uwsgi_sendfile(PyObject * self, PyObject * args) {
struct wsgi_request *wsgi_req = current_wsgi_req();
if (!PyArg_ParseTuple(args, "O|i:uwsgi_sendfile", &wsgi_req->async_sendfile, &wsgi_req->sendfile_fd_chunk)) {
return NULL;
}
#ifdef PYTHREE
wsgi_req->sendfile_fd = PyObject_AsFileDescriptor(wsgi_req->async_sendfile);
#else
if (PyFile_Check((PyObject *)wsgi_req->async_sendfile)) {
Py_INCREF((PyObject *)wsgi_req->async_sendfile);
wsgi_req->sendfile_fd = PyObject_AsFileDescriptor(wsgi_req->async_sendfile);
}
#endif
// PEP 333 hack
wsgi_req->sendfile_obj = wsgi_req->async_sendfile;
//wsgi_req->sendfile_obj = (void *) PyTuple_New(0);
Py_INCREF((PyObject *) wsgi_req->sendfile_obj);
return (PyObject *) wsgi_req->sendfile_obj;
}
#endif
+163
View File
@@ -0,0 +1,163 @@
#include "uwsgi_python.h"
extern struct uwsgi_server uwsgi;
extern struct uwsgi_python up;
static char *nl = "\r\n";
static char *h_sep = ": ";
static const char *http_protocol = "HTTP/1.1";
// check here
PyObject *py_uwsgi_spit(PyObject * self, PyObject * args) {
PyObject *headers, *head;
PyObject *h_key, *h_value;
int i, j;
struct wsgi_request *wsgi_req = current_wsgi_req();
int base = 0;
int shift = 0;
// use writev()
// is a Web3 response ?
/*
if (PyTuple_Size(args) == 3) {
shift = 0;
}
*/
uwsgi_log("HEADERS !!!!\n");
head = PyTuple_GetItem(args, 0+shift);
if (!head) {
goto clear;
}
if (!PyString_Check(head)) {
uwsgi_log( "http status must be a string !\n");
goto clear;
}
if (uwsgi.shared->options[UWSGI_OPTION_CGI_MODE] == 0) {
base = 4;
if (wsgi_req->protocol_len == 0) {
wsgi_req->hvec[0].iov_base = (char *) http_protocol;
wsgi_req->protocol_len = 8;
}
else {
wsgi_req->hvec[0].iov_base = wsgi_req->protocol;
}
wsgi_req->hvec[0].iov_len = wsgi_req->protocol_len;
wsgi_req->hvec[1].iov_base = " ";
wsgi_req->hvec[1].iov_len = 1;
#ifdef PYTHREE
wsgi_req->hvec[2].iov_base = PyBytes_AsString(PyUnicode_AsASCIIString(head));
wsgi_req->hvec[2].iov_len = strlen(wsgi_req->hvec[2].iov_base);
#else
wsgi_req->hvec[2].iov_base = PyString_AsString(head);
wsgi_req->hvec[2].iov_len = PyString_Size(head);
#endif
wsgi_req->status = atoi(wsgi_req->hvec[2].iov_base);
wsgi_req->hvec[3].iov_base = nl;
wsgi_req->hvec[3].iov_len = NL_SIZE;
}
else {
// drop http status on cgi mode
base = 3;
wsgi_req->hvec[0].iov_base = "Status: ";
wsgi_req->hvec[0].iov_len = 8;
#ifdef PYTHREE
wsgi_req->hvec[1].iov_base = PyBytes_AsString(PyUnicode_AsASCIIString(head));
wsgi_req->hvec[1].iov_len = strlen(wsgi_req->hvec[1].iov_base);
#else
wsgi_req->hvec[1].iov_base = PyString_AsString(head);
wsgi_req->hvec[1].iov_len = PyString_Size(head);
#endif
wsgi_req->status = atoi(wsgi_req->hvec[1].iov_base);
wsgi_req->hvec[2].iov_base = nl;
wsgi_req->hvec[2].iov_len = NL_SIZE;
}
headers = PyTuple_GetItem(args, 1+shift);
if (!headers) {
goto clear;
}
if (!PyList_Check(headers)) {
uwsgi_log( "http headers must be in a python list\n");
goto clear;
}
wsgi_req->header_cnt = PyList_Size(headers);
if (wsgi_req->header_cnt > uwsgi.max_vars) {
wsgi_req->header_cnt = uwsgi.max_vars;
}
for (i = 0; i < wsgi_req->header_cnt; i++) {
j = (i * 4) + base;
head = PyList_GetItem(headers, i);
if (!head) {
goto clear;
}
if (!PyTuple_Check(head)) {
uwsgi_log( "http header must be defined in a tuple !\n");
goto clear;
}
h_key = PyTuple_GetItem(head, 0);
if (!h_key) {
goto clear;
}
h_value = PyTuple_GetItem(head, 1);
if (!h_value) {
goto clear;
}
#ifdef PYTHREE
wsgi_req->hvec[j].iov_base = PyBytes_AsString(PyUnicode_AsASCIIString(h_key));
wsgi_req->hvec[j].iov_len = strlen(wsgi_req->hvec[j].iov_base);
#else
wsgi_req->hvec[j].iov_base = PyString_AsString(h_key);
wsgi_req->hvec[j].iov_len = PyString_Size(h_key);
#endif
wsgi_req->hvec[j + 1].iov_base = h_sep;
wsgi_req->hvec[j + 1].iov_len = H_SEP_SIZE;
#ifdef PYTHREE
wsgi_req->hvec[j + 2].iov_base = PyBytes_AsString(PyUnicode_AsASCIIString(h_value));
wsgi_req->hvec[j + 2].iov_len = strlen(wsgi_req->hvec[j + 2].iov_base);
#else
wsgi_req->hvec[j + 2].iov_base = PyString_AsString(h_value);
wsgi_req->hvec[j + 2].iov_len = PyString_Size(h_value);
#endif
wsgi_req->hvec[j + 3].iov_base = nl;
wsgi_req->hvec[j + 3].iov_len = NL_SIZE;
//uwsgi_log( "%.*s: %.*s\n", wsgi_req->hvec[j].iov_len, (char *)wsgi_req->hvec[j].iov_base, wsgi_req->hvec[j+2].iov_len, (char *) wsgi_req->hvec[j+2].iov_base);
}
// \r\n
j = (i * 4) + base;
wsgi_req->hvec[j].iov_base = nl;
wsgi_req->hvec[j].iov_len = NL_SIZE;
UWSGI_RELEASE_GIL
wsgi_req->headers_size = writev(wsgi_req->poll.fd, wsgi_req->hvec, j + 1);
UWSGI_GET_GIL
if (wsgi_req->headers_size < 0) {
uwsgi_error("writev()");
}
Py_INCREF(up.wsgi_writeout);
return up.wsgi_writeout;
clear:
Py_INCREF(Py_None);
return Py_None;
}
+223
View File
@@ -0,0 +1,223 @@
#include "uwsgi_python.h"
extern struct uwsgi_server uwsgi;
extern struct uwsgi_python up;
void *uwsgi_request_subhandler_wsgi(struct wsgi_request *wsgi_req, struct uwsgi_app *wi) {
PyObject *wsgi_socket, *zero;
//static PyObject *uwsgi_version = NULL;
/*
if (uwsgi_version == NULL) {
uwsgi_version = PyString_FromString(UWSGI_VERSION);
}
*/
wsgi_socket = PyFile_FromFile(wsgi_req->async_post, "wsgi_input", "r", NULL);
PyDict_SetItemString(wsgi_req->async_environ, "wsgi.input", wsgi_socket);
Py_DECREF(wsgi_socket);
#ifdef UWSGI_SENDFILE
PyDict_SetItemString(wsgi_req->async_environ, "wsgi.file_wrapper", wi->sendfile);
#endif
#ifdef UWSGI_ASYNC
if (uwsgi.async > 1) {
PyDict_SetItemString(wsgi_req->async_environ, "x-wsgiorg.fdevent.readable", wi->eventfd_read);
PyDict_SetItemString(wsgi_req->async_environ, "x-wsgiorg.fdevent.writable", wi->eventfd_write);
PyDict_SetItemString(wsgi_req->async_environ, "x-wsgiorg.fdevent.timeout", Py_None);
}
#endif
// cache this
zero = PyTuple_New(2);
PyTuple_SetItem(zero, 0, PyInt_FromLong(1));
PyTuple_SetItem(zero, 1, PyInt_FromLong(0));
PyDict_SetItemString(wsgi_req->async_environ, "wsgi.version", zero);
Py_DECREF(zero);
zero = PyFile_FromFile(stderr, "wsgi_input", "w", NULL);
PyDict_SetItemString(wsgi_req->async_environ, "wsgi.errors", zero);
Py_DECREF(zero);
PyDict_SetItemString(wsgi_req->async_environ, "wsgi.run_once", Py_False);
if (uwsgi.threads > 1) {
PyDict_SetItemString(wsgi_req->async_environ, "wsgi.multithread", Py_True);
}
else {
PyDict_SetItemString(wsgi_req->async_environ, "wsgi.multithread", Py_False);
}
if (uwsgi.numproc == 1) {
PyDict_SetItemString(wsgi_req->async_environ, "wsgi.multiprocess", Py_False);
}
else {
PyDict_SetItemString(wsgi_req->async_environ, "wsgi.multiprocess", Py_True);
}
if (wsgi_req->scheme_len > 0) {
zero = PyString_FromStringAndSize(wsgi_req->scheme, wsgi_req->scheme_len);
}
else if (wsgi_req->https_len > 0) {
if (!strncasecmp(wsgi_req->https, "on", 2) || wsgi_req->https[0] == '1') {
zero = PyString_FromString("https");
}
else {
zero = PyString_FromString("http");
}
}
else {
zero = PyString_FromString("http");
}
PyDict_SetItemString(wsgi_req->async_environ, "wsgi.url_scheme", zero);
Py_DECREF(zero);
uwsgi_log("subhandler ok\n");
wsgi_req->async_app = wi->callable ;
//PyDict_SetItemString(uwsgi.embedded_dict, "env", wsgi_req->async_environ);
//PyDict_SetItemString(wsgi_req->async_environ, "uwsgi.version", uwsgi_version);
PyDict_SetItemString(wsgi_req->async_environ, "uwsgi.core", PyInt_FromLong(wsgi_req->async_id));
#ifdef UWSGI_ROUTING
uwsgi_log("routing %d routes %d\n", uwsgi.routing, uwsgi.nroutes);
if (uwsgi.routing && uwsgi.nroutes > 0) {
check_route(uwsgi, wsgi_req);
}
#endif
// call
PyTuple_SetItem(wsgi_req->async_args, 0, wsgi_req->async_environ);
uwsgi_log("subhandler2 ok %p %p %p\n", wsgi_req->async_app, wsgi_req->async_args, wsgi_req->async_environ );
return python_call(wsgi_req->async_app, wsgi_req->async_args, up.catch_exceptions);
}
int uwsgi_response_subhandler_wsgi(struct wsgi_request *wsgi_req) {
PyObject *pychunk ;
ssize_t wsize ;
#ifdef UWSGI_SENDFILE
ssize_t sf_len = 0 ;
#endif
UWSGI_GET_GIL
// 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 UWSGI_SENDFILE
if (wsgi_req->sendfile_obj == wsgi_req->async_result && wsgi_req->sendfile_fd != -1) {
sf_len = uwsgi_sendfile(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) {
UWSGI_RELEASE_GIL
return UWSGI_AGAIN;
}
}
#endif
goto clear;
}
#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) {
UWSGI_RELEASE_GIL
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 UWSGI_SENDFILE
else if (wsgi_req->sendfile_obj == pychunk && wsgi_req->sendfile_fd != -1) {
sf_len = uwsgi_sendfile(wsgi_req);
if (sf_len < 1) goto clear;
wsgi_req->response_size += sf_len ;
}
#endif
Py_DECREF(pychunk);
UWSGI_RELEASE_GIL
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);
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);
}
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
UWSGI_RELEASE_GIL
return UWSGI_OK;
}