Files
uwsgi/plugins/python/python_plugin.c
2011-02-24 09:48:28 +01:00

968 lines
22 KiB
C

#include "uwsgi_python.h"
extern struct uwsgi_server uwsgi;
struct uwsgi_python up;
extern PyTypeObject uwsgi_InputType;
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},
{"pymodule-alias", required_argument, 0, LONG_ARGS_PYMODULE_ALIAS},
{"pp", required_argument, 0, LONG_ARGS_PYTHONPATH},
{"pyargv", required_argument, 0, LONG_ARGS_PYARGV},
{"optimize", required_argument, 0, 'O'},
{"paste", required_argument, 0, LONG_ARGS_PASTE},
#ifdef UWSGI_INI
{"ini-paste", required_argument, 0, LONG_ARGS_INI_PASTE},
#endif
{"catch-exceptions", no_argument, &up.catch_exceptions, 1},
{"ignore-script-name", no_argument, &up.ignore_script_name, 1},
{"pep3333-input", no_argument, &up.pep3333_input, 1},
{"reload-os-env", no_argument, &up.reload_os_env, 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() {
char *pyversion = strchr(Py_GetVersion(), '\n');
uwsgi_log("Python version: %.*s %s\n", pyversion-Py_GetVersion(), Py_GetVersion(), Py_GetCompiler()+1);
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();
// by default set a fake GIL (little impact on performance)
up.gil_get = gil_fake_get;
up.gil_release = gil_fake_release;
up.swap_ts = simple_swap_ts;
up.reset_ts = simple_reset_ts;
uwsgi_log("Python main interpreter initialized at %p\n", up.main_thread);
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
}
PyObject *uwsgi_pyimport_by_filename(char *name, char *filename) {
FILE *pyfile;
struct _node *py_file_node = NULL;
PyObject *py_compiled_node, *py_file_module;
int is_a_package = 0;
struct stat pystat;
char *real_filename = filename;
pyfile = fopen(filename, "r");
if (!pyfile) {
uwsgi_log("failed to open python file %s\n", filename);
exit(1);
}
if (fstat(fileno(pyfile), &pystat)) {
uwsgi_error("fstat()");
exit(1);
}
if (S_ISDIR(pystat.st_mode)) {
is_a_package = 1;
fclose(pyfile);
real_filename = uwsgi_concat2(filename, "/__init__.py");
pyfile = fopen(real_filename, "r");
if (!pyfile) {
uwsgi_error("fopen()");
exit(1);
}
}
py_file_node = PyParser_SimpleParseFile(pyfile, real_filename, Py_file_input);
if (!py_file_node) {
PyErr_Print();
uwsgi_log("failed to parse file %s\n", real_filename);
exit(1);
}
fclose(pyfile);
py_compiled_node = (PyObject *) PyNode_Compile(py_file_node, real_filename);
if (!py_compiled_node) {
PyErr_Print();
uwsgi_log("failed to compile python file %s\n", real_filename);
exit(1);
}
py_file_module = PyImport_ExecCodeModule(name, py_compiled_node);
if (!py_file_module) {
PyErr_Print();
exit(1);
}
Py_DECREF(py_compiled_node);
if (is_a_package) {
PyObject *py_file_module_dict = PyModule_GetDict(py_file_module);
if (py_file_module_dict) {
PyDict_SetItemString(py_file_module_dict, "__path__", Py_BuildValue("[O]", PyString_FromString(filename)));
}
free(real_filename);
}
return py_file_module;
}
void init_uwsgi_vars() {
int i;
PyObject *pysys, *pysys_dict, *pypath;
PyObject *modules = PyImport_GetModuleDict();
PyObject *tmp_module;
#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]);
}
}
for (i = 0; i < up.pymodule_alias_cnt; i++) {
// split key=value
char *value = strchr(up.pymodule_alias[i], '=');
if (!value) {
uwsgi_log("invalid pymodule-alias syntax\n");
continue;
}
value[0] = 0;
if (!strchr(value + 1, '/')) {
// this is a standard pymodule
tmp_module = PyImport_ImportModule(value + 1);
if (!tmp_module) {
PyErr_Print();
exit(1);
}
PyDict_SetItemString(modules, up.pymodule_alias[i], tmp_module);
}
else {
// this is a filepath that need to be mapped
tmp_module = uwsgi_pyimport_by_filename(up.pymodule_alias[i], value + 1);
}
uwsgi_log("mapped virtual pymodule \"%s\" to real pymodule \"%s\"\n", up.pymodule_alias[i], value + 1);
// reset original value
value[0] = '=';
}
}
#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;
PyType_Ready(&uwsgi_InputType);
/* initialize for stats */
up.workers_tuple = PyTuple_New(uwsgi.numproc);
for (i = 0; i < uwsgi.numproc; i++) {
zero = PyDict_New();
Py_INCREF(zero);
PyTuple_SetItem(up.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);
}
up.embedded_dict = PyModule_GetDict(new_uwsgi_module);
if (!up.embedded_dict) {
uwsgi_log("could not get uwsgi module __dict__\n");
exit(1);
}
if (PyDict_SetItemString(up.embedded_dict, "version", PyString_FromString(UWSGI_VERSION))) {
PyErr_Print();
exit(1);
}
if (uwsgi.mode) {
if (PyDict_SetItemString(up.embedded_dict, "mode", PyString_FromString(uwsgi.mode))) {
PyErr_Print();
exit(1);
}
}
if (uwsgi.pidfile) {
if (PyDict_SetItemString(up.embedded_dict, "pidfile", PyString_FromString(uwsgi.pidfile))) {
PyErr_Print();
exit(1);
}
}
if (PyDict_SetItemString(up.embedded_dict, "SPOOL_RETRY", PyInt_FromLong(-1))) {
PyErr_Print();
exit(1);
}
if (PyDict_SetItemString(up.embedded_dict, "SPOOL_OK", PyInt_FromLong(-2))) {
PyErr_Print();
exit(1);
}
if (PyDict_SetItemString(up.embedded_dict, "SPOOL_IGNORE", PyInt_FromLong(0))) {
PyErr_Print();
exit(1);
}
if (PyDict_SetItemString(up.embedded_dict, "numproc", PyInt_FromLong(uwsgi.numproc))) {
PyErr_Print();
exit(1);
}
if (PyDict_SetItemString(up.embedded_dict, "cores", PyInt_FromLong(uwsgi.cores))) {
PyErr_Print();
exit(1);
}
if (uwsgi.loop) {
if (PyDict_SetItemString(up.embedded_dict, "loop", PyString_FromString(uwsgi.loop))) {
PyErr_Print();
exit(1);
}
}
if (PyDict_SetItemString(up.embedded_dict, "KIND_NULL", PyInt_FromLong(KIND_NULL))) {
PyErr_Print();
exit(1);
}
if (PyDict_SetItemString(up.embedded_dict, "KIND_WORKER", PyInt_FromLong(KIND_WORKER))) {
PyErr_Print();
exit(1);
}
if (PyDict_SetItemString(up.embedded_dict, "KIND_EVENT", PyInt_FromLong(KIND_EVENT))) {
PyErr_Print();
exit(1);
}
if (PyDict_SetItemString(up.embedded_dict, "KIND_SPOOLER", PyInt_FromLong(KIND_SPOOLER))) {
PyErr_Print();
exit(1);
}
/*
if (PyDict_SetItemString(up.embedded_dict, "KIND_ERLANG", PyInt_FromLong(KIND_ERLANG))) {
PyErr_Print();
exit(1);
}
*/
if (PyDict_SetItemString(up.embedded_dict, "KIND_PROXY", PyInt_FromLong(KIND_PROXY))) {
PyErr_Print();
exit(1);
}
if (PyDict_SetItemString(up.embedded_dict, "KIND_MASTER", PyInt_FromLong(KIND_MASTER))) {
PyErr_Print();
exit(1);
}
PyObject *py_opt_dict = PyDict_New();
for (i = 0; i < uwsgi.exported_opts_cnt; i++) {
if (PyDict_Contains(py_opt_dict, PyString_FromString(uwsgi.exported_opts[i]->key))) {
PyObject *py_opt_item = PyDict_GetItemString(py_opt_dict, uwsgi.exported_opts[i]->key);
if (PyList_Check(py_opt_item)) {
PyList_Append(py_opt_item, PyString_FromString(uwsgi.exported_opts[i]->value));
}
else {
PyObject *py_opt_list = PyList_New(0);
PyList_Append(py_opt_list, py_opt_item);
if (uwsgi.exported_opts[i]->value == NULL) {
PyList_Append(py_opt_list, Py_True);
}
else {
PyList_Append(py_opt_list, PyString_FromString(uwsgi.exported_opts[i]->value));
}
PyDict_SetItemString(py_opt_dict, uwsgi.exported_opts[i]->key, py_opt_list);
}
}
else {
if (uwsgi.exported_opts[i]->value == NULL) {
PyDict_SetItemString(py_opt_dict, uwsgi.exported_opts[i]->key, Py_True);
}
else {
PyDict_SetItemString(py_opt_dict, uwsgi.exported_opts[i]->key, PyString_FromString(uwsgi.exported_opts[i]->value));
}
}
}
if (PyDict_SetItemString(up.embedded_dict, "opt", py_opt_dict)) {
PyErr_Print();
exit(1);
}
#ifdef UNBIT
if (PyDict_SetItemString(up.embedded_dict, "unbit", Py_True)) {
#else
if (PyDict_SetItemString(up.embedded_dict, "unbit", Py_None)) {
#endif
PyErr_Print();
exit(1);
}
if (PyDict_SetItemString(up.embedded_dict, "buffer_size", PyInt_FromLong(uwsgi.buffer_size))) {
PyErr_Print();
exit(1);
}
if (PyDict_SetItemString(up.embedded_dict, "started_on", PyInt_FromLong(uwsgi.start_tv.tv_sec))) {
PyErr_Print();
exit(1);
}
if (PyDict_SetItemString(up.embedded_dict, "start_response", up.wsgi_spitout)) {
PyErr_Print();
exit(1);
}
if (PyDict_SetItemString(up.embedded_dict, "fastfuncs", PyList_New(256))) {
PyErr_Print();
exit(1);
}
if (PyDict_SetItemString(up.embedded_dict, "applications", Py_None)) {
PyErr_Print();
exit(1);
}
if (uwsgi.is_a_reload) {
if (PyDict_SetItemString(up.embedded_dict, "is_a_reload", Py_True)) {
PyErr_Print();
exit(1);
}
}
else {
if (PyDict_SetItemString(up.embedded_dict, "is_a_reload", Py_False)) {
PyErr_Print();
exit(1);
}
}
up.embedded_args = PyTuple_New(2);
if (!up.embedded_args) {
PyErr_Print();
exit(1);
}
if (PyDict_SetItemString(up.embedded_dict, "message_manager_marshal", Py_None)) {
PyErr_Print();
exit(1);
}
up.fastfuncslist = PyDict_GetItemString(up.embedded_dict, "fastfuncs");
if (!up.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);
}
init_uwsgi_module_cache(new_uwsgi_module);
init_uwsgi_module_queue(new_uwsgi_module);
if (up.extension) {
up.extension();
}
}
#endif
int uwsgi_python_magic(char *mountpoint, char *lazy) {
char *qc = strchr(lazy, ':');
if (qc) {
qc[0] = 0;
up.callable = qc + 1;
}
if (!strcmp(lazy + strlen(lazy) - 3, ".py")) {
up.file_config = lazy;
return 1;
}
else if (!strcmp(lazy + strlen(lazy) - 5, ".wsgi")) {
up.file_config = lazy;
return 1;
}
else if (qc && strchr(lazy, '.')) {
up.wsgi_config = lazy;
return 1;
}
// reset lazy
if (qc) {
qc[0] = ':';
}
return 0;
}
int uwsgi_python_manage_options(int i, char *optarg) {
switch (i) {
case 'w':
up.wsgi_config = optarg;
return 1;
case LONG_ARGS_WSGI_FILE:
case LONG_ARGS_FILE_CONFIG:
up.file_config = optarg;
return 1;
case LONG_ARGS_PYMODULE_ALIAS:
if (up.pymodule_alias_cnt < MAX_PYMODULE_ALIAS) {
up.pymodule_alias[up.pymodule_alias_cnt] = optarg;
up.pymodule_alias_cnt++;
}
else {
uwsgi_log("you can specify at most %d --pymodule-alias options\n", MAX_PYMODULE_ALIAS);
}
return 1;
case LONG_ARGS_PYTHONPATH:
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 'O':
up.optimize = atoi(optarg);
return 1;
case LONG_ARGS_CALLABLE:
up.callable = optarg;
return 1;
case LONG_ARGS_INI_PASTE:
uwsgi.ini = optarg;
if (uwsgi.ini[0] != '/') {
up.paste = uwsgi_concat4("config:", uwsgi.cwd, "/", uwsgi.ini);
}
else {
up.paste = uwsgi_concat2("config:", uwsgi.ini);
}
return 1;
case LONG_ARGS_PASTE:
up.paste = optarg;
return 1;
}
return 0;
}
int uwsgi_python_mount_app(char *mountpoint, char *app) {
uwsgi.wsgi_req->script_name = mountpoint;
uwsgi.wsgi_req->script_name_len = strlen(mountpoint);
if (uwsgi.single_interpreter) {
return init_uwsgi_app(LOADER_MOUNT, app, uwsgi.wsgi_req, up.main_thread);
}
return init_uwsgi_app(LOADER_MOUNT, app, uwsgi.wsgi_req, NULL);
}
void uwsgi_python_init_apps() {
init_pyargv();
#ifdef UWSGI_MINTERPRETERS
init_uwsgi_embedded_module();
#endif
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;
up.loaders[LOADER_PASTE] = uwsgi_paste_loader;
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;
if (up.wsgi_config != NULL) {
init_uwsgi_app(LOADER_UWSGI, up.wsgi_config, uwsgi.wsgi_req, up.main_thread);
}
if (up.file_config != NULL) {
init_uwsgi_app(LOADER_FILE, up.file_config, uwsgi.wsgi_req, up.main_thread);
}
if (up.paste != NULL) {
init_uwsgi_app(LOADER_PASTE, up.paste, uwsgi.wsgi_req, up.main_thread);
}
if (up.eval != NULL) {
init_uwsgi_app(LOADER_EVAL, up.eval, uwsgi.wsgi_req, up.main_thread);
}
}
void uwsgi_python_enable_threads() {
PyEval_InitThreads();
if (pthread_key_create(&up.upt_save_key, NULL)) {
uwsgi_error("pthread_key_create()");
exit(1);
}
if (pthread_key_create(&up.upt_gil_key, NULL)) {
uwsgi_error("pthread_key_create()");
exit(1);
}
pthread_setspecific(up.upt_save_key, (void *) PyThreadState_Get());
pthread_setspecific(up.upt_gil_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;
up.swap_ts = threaded_swap_ts;
up.reset_ts = threaded_reset_ts;
uwsgi_log("threads support enabled\n");
}
void uwsgi_python_init_thread(int core_id) {
// set a new ThreadState for each thread
PyThreadState *pts;
pts = PyThreadState_New(up.main_thread->interp);
pthread_setspecific(up.upt_save_key, (void *) pts);
pthread_setspecific(up.upt_gil_key, (void *) pts);
}
int uwsgi_python_xml(char *node, char *content) {
PyThreadState *interpreter = NULL;
if (uwsgi.single_interpreter) {
interpreter = up.main_thread;
}
if (!strcmp("script", node)) {
return init_uwsgi_app(LOADER_UWSGI, content, uwsgi.wsgi_req, interpreter);
}
else if (!strcmp("file", node)) {
return init_uwsgi_app(LOADER_FILE, content, uwsgi.wsgi_req, interpreter);
}
else if (!strcmp("eval", node)) {
return init_uwsgi_app(LOADER_EVAL, content, uwsgi.wsgi_req, interpreter);
}
else if (!strcmp("wsgi", node)) {
return init_uwsgi_app(LOADER_EVAL, content, uwsgi.wsgi_req, interpreter);
}
else if (!strcmp("module", node)) {
uwsgi.wsgi_req->module = content;
uwsgi.wsgi_req->module_len = strlen(content);
uwsgi.wsgi_req->callable = strchr(uwsgi.wsgi_req->module, ':');
if (uwsgi.wsgi_req->callable) {
uwsgi.wsgi_req->callable[0] = 0;
uwsgi.wsgi_req->callable++;
uwsgi.wsgi_req->callable_len = strlen(uwsgi.wsgi_req->callable);
uwsgi.wsgi_req->module_len = strlen(uwsgi.wsgi_req->module);
return init_uwsgi_app(LOADER_DYN, uwsgi.wsgi_req, uwsgi.wsgi_req, interpreter);
}
return 1;
}
else if (!strcmp("pyhome", node)) {
uwsgi.wsgi_req->pyhome = content;
uwsgi.wsgi_req->pyhome_len = strlen(content);
return 1;
}
else if (!strcmp("callable", node)) {
uwsgi.wsgi_req->callable = content;
uwsgi.wsgi_req->callable_len = strlen(content);
return init_uwsgi_app(LOADER_DYN, uwsgi.wsgi_req, uwsgi.wsgi_req, interpreter);
}
return 0;
}
void uwsgi_python_suspend(struct wsgi_request *wsgi_req) {
PyThreadState *tstate = PyThreadState_GET();
uwsgi_log("suspending python\n");
up.current_recursion_depth = tstate->recursion_depth;
up.current_frame = tstate->frame;
}
int uwsgi_python_signal_handler(uint8_t sig, void *handler) {
PyObject *args = PyTuple_New(1);
PyObject *ret;
if (!args)
return -1;
PyTuple_SetItem(args, 0, PyInt_FromLong(sig));
ret = python_call(handler, args, 0);
if (ret) {
return 0;
}
return -1;
}
uint16_t uwsgi_python_rpc(void *func, uint8_t argc, char **argv, char *buffer) {
uint8_t i;
PyObject *pyargs = PyTuple_New(argc);
PyObject *ret;
char *rv;
size_t rl;
if (!pyargs)
return 0;
for (i = 0; i < argc; i++) {
PyTuple_SetItem(pyargs, i, PyString_FromString(argv[i]));
}
ret = python_call((PyObject *) func, pyargs, 0);
if (ret) {
if (PyString_Check(ret)) {
rv = PyString_AsString(ret);
rl = strlen(rv);
if (rl <= 0xffff) {
memcpy(buffer, rv, rl);
Py_DECREF(ret);
return rl;
}
}
}
if (PyErr_Occurred())
PyErr_Print();
return 0;
}
void uwsgi_python_add_item(char *key, uint16_t keylen, char *val, uint16_t vallen, void *data) {
PyObject *pydict = (PyObject *) data;
PyDict_SetItem(pydict, PyString_FromStringAndSize(key, keylen), PyString_FromStringAndSize(val, vallen));
}
int uwsgi_python_spooler(char *buf, uint16_t len) {
PyObject *spool_dict = PyDict_New();
PyObject *spool_func, *pyargs, *ret;
if (!up.embedded_dict) {
// ignore
return 0;
}
spool_func = PyDict_GetItemString(up.embedded_dict, "spooler");
if (!spool_func) {
// ignore
return 0;
}
if (uwsgi_hooked_parse(buf, len, uwsgi_python_add_item, spool_dict)) {
// malformed packet, destroy it
return -2;
}
pyargs = PyTuple_New(1);
PyTuple_SetItem(pyargs, 0, spool_dict);
ret = python_call(spool_func, pyargs, 0);
if (ret) {
if (!PyInt_Check(ret)) {
// error, retry
return -1;
}
return PyInt_AsLong(ret);
}
if (PyErr_Occurred())
PyErr_Print();
// error, retry
return -1;
}
void uwsgi_python_resume(struct wsgi_request *wsgi_req) {
PyThreadState *tstate = PyThreadState_GET();
uwsgi_log("resuming python\n");
tstate->recursion_depth = up.current_recursion_depth;
tstate->frame = up.current_frame;
}
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,
.short_options = "w:O:H:j:",
.request = uwsgi_request_wsgi,
.after_request = uwsgi_after_request_wsgi,
.init_apps = uwsgi_python_init_apps,
.mount_app = uwsgi_python_mount_app,
.enable_threads = uwsgi_python_enable_threads,
.init_thread = uwsgi_python_init_thread,
.manage_xml = uwsgi_python_xml,
.magic = uwsgi_python_magic,
.suspend = uwsgi_python_suspend,
.resume = uwsgi_python_resume,
.signal_handler = uwsgi_python_signal_handler,
.rpc = uwsgi_python_rpc,
.spooler = uwsgi_python_spooler,
/*
.help = uwsgi_python_help,
*/
};