mirror of
https://github.com/clearlinux/uwsgi.git
synced 2026-08-26 16:28:00 +00:00
add new files to the tree
This commit is contained in:
@@ -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.
@@ -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() {}
|
||||
@@ -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));
|
||||
}
|
||||
@@ -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,
|
||||
*/
|
||||
|
||||
};
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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);
|
||||
@@ -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.
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user