From a44879e3841bdda90d725b30f5abd40a19a12dc1 Mon Sep 17 00:00:00 2001 From: "roberto@oneiric64" Date: Tue, 29 Nov 2011 07:47:19 +0100 Subject: [PATCH] improved lazy mode to allows signals --- plugins/python/pyloader.c | 25 +++++++++-------- plugins/python/python_plugin.c | 51 ++++++++++++++++++++++++++-------- plugins/python/uwsgi_python.h | 2 ++ signal.c | 33 ++++++++++++++++++++-- uwsgi.c | 13 +++++++++ uwsgi.h | 2 ++ uwsgidecorators.py | 3 -- 7 files changed, 100 insertions(+), 29 deletions(-) diff --git a/plugins/python/pyloader.c b/plugins/python/pyloader.c index 882cf506..0af77042 100644 --- a/plugins/python/pyloader.c +++ b/plugins/python/pyloader.c @@ -370,24 +370,25 @@ int init_uwsgi_app(int loader, void *arg1, struct wsgi_request *wsgi_req, PyThre PyThreadState_Swap(up.main_thread); } - if (app_type == PYTHON_APP_TYPE_WSGI) { - uwsgi_log( "WSGI application %d (mountpoint='%.*s') ready on interpreter %p pid: %d", id, wi->mountpoint_len, wi->mountpoint, wi->interpreter, (int) getpid()); - } - else if (app_type == PYTHON_APP_TYPE_WEB3) { - uwsgi_log( "Web3 application %d (mountpoint='%.*s') ready on interpreter %p pid: %d", id, wi->mountpoint_len, wi->mountpoint, wi->interpreter, (int) getpid()); - } - else if (app_type == PYTHON_APP_TYPE_PUMP) { - uwsgi_log( "Pump application %d (mountpoint='%.*s') ready on interpreter %p pid: %d", id, wi->mountpoint_len, wi->mountpoint, wi->interpreter, (int) getpid()); - } + const char *default_app = ""; if ((wsgi_req->appid_len == 0 || (wsgi_req->appid_len = 1 && wsgi_req->appid[0] == '/')) && uwsgi.default_app == -1) { - uwsgi_rawlog(" (default app)"); + default_app = " (default app)" ; uwsgi.default_app = id; } - uwsgi_apps_cnt++; + if (app_type == PYTHON_APP_TYPE_WSGI) { + uwsgi_log( "WSGI application %d (mountpoint='%.*s') ready on interpreter %p pid: %d%s\n", id, wi->mountpoint_len, wi->mountpoint, wi->interpreter, (int) getpid(), default_app); + } + else if (app_type == PYTHON_APP_TYPE_WEB3) { + uwsgi_log( "Web3 application %d (mountpoint='%.*s') ready on interpreter %p pid: %d%s\n", id, wi->mountpoint_len, wi->mountpoint, wi->interpreter, (int) getpid(), default_app); + } + else if (app_type == PYTHON_APP_TYPE_PUMP) { + uwsgi_log( "Pump application %d (mountpoint='%.*s') ready on interpreter %p pid: %d%s\n", id, wi->mountpoint_len, wi->mountpoint, wi->interpreter, (int) getpid(), default_app); + } - uwsgi_rawlog("\n"); + + uwsgi_apps_cnt++; if (multiapp > 1) { for(i=1;i 1) { - up.current_recursion_depth = uwsgi_malloc(sizeof(int)*uwsgi.async); -#ifndef UWSGI_PYPY - up.current_frame = uwsgi_malloc(sizeof(struct _frame)*uwsgi.async); -#endif - } +// this hook will be executed by master (or worker1 when master is not requested, so COW is in place) +void uwsgi_python_preinit_apps() { init_pyargv(); @@ -912,7 +910,6 @@ void uwsgi_python_init_apps() { #endif #endif - #ifdef __linux__ #ifndef UWSGI_PYPY #ifdef UWSGI_EMBEDDED @@ -930,6 +927,34 @@ void uwsgi_python_init_apps() { init_uwsgi_vars(); + // load shared imports + struct uwsgi_string_list *upli = up.shared_import_list; + while(upli) { + if (strchr(upli->value, '/') || uwsgi_endswith(upli->value, ".py")) { + uwsgi_pyimport_by_filename(uwsgi_pythonize(upli->value), upli->value); + } + else { + if (PyImport_ImportModule(upli->value) == NULL) { + PyErr_Print(); + } + } + upli = upli->next; + } + +} + +void uwsgi_python_init_apps() { + + struct http_status_codes *http_sc; + + // prepare for stack suspend/resume + if (uwsgi.async > 1) { + up.current_recursion_depth = uwsgi_malloc(sizeof(int)*uwsgi.async); +#ifndef UWSGI_PYPY + up.current_frame = uwsgi_malloc(sizeof(struct _frame)*uwsgi.async); +#endif + } + // setup app loaders #ifdef UWSGI_MINTERPRETERS up.loaders[LOADER_DYN] = uwsgi_dyn_loader; @@ -1479,6 +1504,8 @@ struct uwsgi_plugin python_plugin = { .short_options = "w:O:H:J:", .request = uwsgi_request_wsgi, .after_request = uwsgi_after_request_wsgi, + + .preinit_apps = uwsgi_python_preinit_apps, .init_apps = uwsgi_python_init_apps, .fixup = uwsgi_python_fixup, diff --git a/plugins/python/uwsgi_python.h b/plugins/python/uwsgi_python.h index 975e3062..203d27ee 100644 --- a/plugins/python/uwsgi_python.h +++ b/plugins/python/uwsgi_python.h @@ -21,6 +21,7 @@ #define LONG_ARGS_PYSHELL LONG_ARGS_PYTHON_BASE + 11 #define LONG_ARGS_SPOOLER_PYIMPORT LONG_ARGS_PYTHON_BASE + 12 #define LONG_ARGS_PYTHON_RUN LONG_ARGS_PYTHON_BASE + 13 +#define LONG_ARGS_SHARED_PYIMPORT LONG_ARGS_PYTHON_BASE + 14 #define PYTHON_APP_TYPE_WSGI 0 #define PYTHON_APP_TYPE_WEB3 1 @@ -133,6 +134,7 @@ struct uwsgi_python { struct uwsgi_string_list *python_path; struct uwsgi_string_list *import_list; + struct uwsgi_string_list *shared_import_list; struct uwsgi_string_list *spooler_import_list; struct uwsgi_string_list *post_pymodule_alias; diff --git a/signal.c b/signal.c index f0d83881..fc267802 100644 --- a/signal.c +++ b/signal.c @@ -12,6 +12,28 @@ int uwsgi_signal_handler(uint8_t sig) { return -1; } + // check for COW + if (uwsgi.master_process) { + if (use->wid != 0 && use->wid != uwsgi.mywid) { + uwsgi_log("[uwsgi-signal] you have registered this signal in worker %d memory area, only that process will be able to run it\n", use->wid); + return -1; + } + } + // in lazy mode (without a master), only the same worker will be able to run handlers + else if (uwsgi.lazy) { + if (use->wid != uwsgi.mywid) { + uwsgi_log("[uwsgi-signal] you have registered this signal in worker %d memory area, only that process will be able to run it\n", use->wid); + return -1; + } + } + else { + // when master is not active, worker1 is the COW-leader + if (use->wid != 1 && use->wid != uwsgi.mywid) { + uwsgi_log("[uwsgi-signal] you have registered this signal in worker %d memory area, only that process will be able to run it\n", use->wid); + return -1; + } + } + // set harakiri here (if required and if i am a worker) if (uwsgi.mywid > 0) { @@ -81,15 +103,22 @@ int uwsgi_register_signal(uint8_t sig, char *receiver, void *handler, uint8_t mo use = &uwsgi.shared->signal_table[sig]; + if (use->handler) { + uwsgi_log("[uwsgi-signal] you cannot re-register a signal !!!\n"); + uwsgi_unlock(uwsgi.signal_table_lock); + return -1; + } + strcpy(use->receiver, receiver); use->handler = handler; use->modifier1 = modifier1; + use->wid = uwsgi.mywid; if (use->receiver[0] == 0) { - uwsgi_log("[uwsgi-signal] signum %d registered (modifier1: %d target: default, any worker)\n", sig, modifier1); + uwsgi_log("[uwsgi-signal] signum %d registered (wid: %d modifier1: %d target: default, any worker)\n", sig, uwsgi.mywid, modifier1); } else { - uwsgi_log("[uwsgi-signal] signum %d registered (modifier1: %d target: %s)\n", sig, modifier1, receiver); + uwsgi_log("[uwsgi-signal] signum %d registered (wid: %d modifier1: %d target: %s)\n", sig, uwsgi.mywid, modifier1, receiver); } uwsgi_unlock(uwsgi.signal_table_lock); diff --git a/uwsgi.c b/uwsgi.c index d0419c94..2f2e7602 100644 --- a/uwsgi.c +++ b/uwsgi.c @@ -2441,6 +2441,19 @@ skipzero: memset(uwsgi.core[j], 0, sizeof(struct uwsgi_core)); } + // preinit apps (create the language environment) + for (i = 0; i < 0xFF; i++) { + if (uwsgi.p[i]->preinit_apps) { + uwsgi.p[i]->preinit_apps(); + } + } + + for (i = 0; i < uwsgi.gp_cnt; i++) { + if (uwsgi.gp[i]->preinit_apps) { + uwsgi.gp[i]->preinit_apps(); + } + } + //init apps hook (if not lazy) if (!uwsgi.lazy) { uwsgi_init_all_apps(); diff --git a/uwsgi.h b/uwsgi.h index 5fddfe25..8f197b16 100644 --- a/uwsgi.h +++ b/uwsgi.h @@ -656,6 +656,7 @@ struct uwsgi_plugin { int (*request) (struct wsgi_request *); void (*after_request) (struct wsgi_request *); void (*init_apps) (void); + void (*preinit_apps) (void); void (*fixup) (void); void (*master_fixup) (int); void (*master_cycle) (void); @@ -1573,6 +1574,7 @@ struct uwsgi_lb_group { struct uwsgi_signal_entry { + int wid; uint8_t modifier1; char receiver[64]; void *handler; diff --git a/uwsgidecorators.py b/uwsgidecorators.py index 076ed678..70909b7c 100644 --- a/uwsgidecorators.py +++ b/uwsgidecorators.py @@ -10,9 +10,6 @@ except: if uwsgi.masterpid() == 0: raise Exception("you have to enable the uWSGI master process to use this module") -if uwsgi.opt.get('lazy'): - raise Exception("uWSGI lazy mode is not supported by this module") - spooler_functions = {} mule_functions = {} postfork_chain = []