diff --git a/plugins/python/python_plugin.c b/plugins/python/python_plugin.c index f02d3b1a..60d74bdd 100644 --- a/plugins/python/python_plugin.c +++ b/plugins/python/python_plugin.c @@ -693,6 +693,26 @@ int uwsgi_python_magic(char *mountpoint, char *lazy) { 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; + +} + +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", @@ -710,6 +730,9 @@ int uwsgi_python_magic(char *mountpoint, char *lazy) { .manage_xml = uwsgi_python_xml, .magic = uwsgi_python_magic, + + .suspend = uwsgi_python_suspend, + .resume = uwsgi_python_resume, //.spooler = uwsgi_python_spooler, /* .help = uwsgi_python_help, diff --git a/plugins/python/uwsgi_python.h b/plugins/python/uwsgi_python.h index 14de23bf..3549b9f2 100644 --- a/plugins/python/uwsgi_python.h +++ b/plugins/python/uwsgi_python.h @@ -86,6 +86,8 @@ struct uwsgi_python { int ignore_script_name; int catch_exceptions; + int current_recursion_depth; + struct _frame* current_frame; #ifdef UWSGI_THREADING pthread_key_t upt_save_key; diff --git a/plugins/rack/rack_plugin.c b/plugins/rack/rack_plugin.c index 139fd724..50cf8f47 100644 --- a/plugins/rack/rack_plugin.c +++ b/plugins/rack/rack_plugin.c @@ -60,6 +60,8 @@ struct uwsgi_rack { pthread_mutex_t gvl; + rb_thread_t context; + } ur; struct option uwsgi_rack_options[] = { @@ -748,11 +750,13 @@ int uwsgi_rack_manage_options(int i, char *optarg) { void uwsgi_rack_suspend(struct wsgi_request *wsgi_req) { uwsgi_log("SUSPENDING RUBY\n"); + rb_thread_save_context(ur.context); } void uwsgi_rack_resume(struct wsgi_request *wsgi_req) { uwsgi_log("RESUMING RUBY\n"); + rb_thread_restore_context(ur.context, RESTORE_NORMAL); } void uwsgi_rack_enable_threads(void) { diff --git a/plugins/ugreen/ugreen.c b/plugins/ugreen/ugreen.c index 5d98ffbe..c83c0d9a 100644 --- a/plugins/ugreen/ugreen.c +++ b/plugins/ugreen/ugreen.c @@ -1,22 +1,34 @@ /* uGreen -> uWSGI green threads */ -#include "../uwsgi.h" +#include "../../uwsgi.h" + +#ifdef __APPLE__ +#define _XOPEN_SOURCE +#endif #include -int ugreen; - int ugreen_stackpages; - ucontext_t ugreenmain; - ucontext_t **ugreen_contexts; +struct uwsgi_ugreen { + int ugreen; + int stackpages; + ucontext_t main; + ucontext_t **contexts; size_t u_stack_size; +} ug; #define UGREEN_DEFAULT_STACKSIZE 256*1024 -{"ugreen", no_argument, &uwsgi.ugreen, 1}, - {"ugreen-stacksize", required_argument, 0, LONG_ARGS_UGREEN_PAGES}, extern struct uwsgi_server uwsgi; +struct option ugreen_options[] = { + {"ugreen", no_argument, &ug.ugreen, 1}, + {"ugreen-stacksize", required_argument, 0, LONG_ARGS_UGREEN_PAGES}, + { 0, 0, 0, 0 } +}; + +void u_green_loop(void); + void u_green_write_all(char *data, size_t len) { struct wsgi_request *wsgi_req; @@ -73,16 +85,16 @@ inline static void u_green_schedule_to_main(int async_id) { struct wsgi_request *wsgi_req = uwsgi.wsgi_requests[async_id]; if (wsgi_req->async_status != UWSGI_ACCEPTING) { - if (uwsgi.shared->hook_suspend[wsgi_req->uh.modifier1]) { - uwsgi.shared->hook_suspend[wsgi_req->uh.modifier1](wsgi_req); + if (uwsgi.p[wsgi_req->uh.modifier1]->suspend) { + uwsgi.p[wsgi_req->uh.modifier1]->suspend(wsgi_req); } } - swapcontext(uwsgi.ugreen_contexts[async_id], &uwsgi.ugreenmain); + swapcontext(ug.contexts[async_id], &ug.main); if (wsgi_req->async_status != UWSGI_ACCEPTING) { - if (uwsgi.shared->hook_resume[wsgi_req->uh.modifier1]) { - uwsgi.shared->hook_resume[wsgi_req->uh.modifier1](wsgi_req); + if (uwsgi.p[wsgi_req->uh.modifier1]->resume) { + uwsgi.p[wsgi_req->uh.modifier1]->resume(wsgi_req); } } } @@ -91,21 +103,21 @@ inline static void u_green_schedule_to_req(struct wsgi_request *wsgi_req) { if (wsgi_req->async_status != UWSGI_ACCEPTING) { - if (uwsgi.shared->hook_suspend[wsgi_req->uh.modifier1]) { - uwsgi.shared->hook_suspend[wsgi_req->uh.modifier1](wsgi_req); + if (uwsgi.p[wsgi_req->uh.modifier1]->suspend) { + uwsgi.p[wsgi_req->uh.modifier1]->suspend(wsgi_req); } } uwsgi.wsgi_req = wsgi_req; - uwsgi_log("SWAPCONTEXT\n"); + uwsgi_log("SWAPCONTEXT to %p\n", ug.contexts[wsgi_req->async_id]); //wsgi_req->async_switches++; - swapcontext(&uwsgi.ugreenmain, uwsgi.ugreen_contexts[wsgi_req->async_id] ); + swapcontext(&ug.main, ug.contexts[wsgi_req->async_id] ); uwsgi_log("RESUMED\n"); if (wsgi_req->async_status != UWSGI_ACCEPTING) { - if (uwsgi.shared->hook_resume[wsgi_req->uh.modifier1]) { - uwsgi.shared->hook_resume[wsgi_req->uh.modifier1](wsgi_req); + if (uwsgi.p[wsgi_req->uh.modifier1]->resume) { + uwsgi.p[wsgi_req->uh.modifier1]->resume(wsgi_req); } } @@ -134,9 +146,9 @@ static struct wsgi_request *find_first_accepting_wsgi_req() { struct wsgi_request* wsgi_req; int i; - uwsgi_log("FFAR\n"); for(i=0;iasync_status); if (wsgi_req->async_status == UWSGI_ACCEPTING) { return wsgi_req; } @@ -148,6 +160,7 @@ static struct wsgi_request *find_first_accepting_wsgi_req() { static void u_green_request(struct wsgi_request *wsgi_req, int async_id) { + uwsgi_log("request handler args %p %d\n", wsgi_req, async_id); for(;;) { uwsgi_log("accept()\n"); @@ -160,6 +173,8 @@ static void u_green_request(struct wsgi_request *wsgi_req, int async_id) { if (wsgi_req_accept(wsgi_req)) { continue; } + + uwsgi_log("REQUEST ACCEPTED\n"); wsgi_req->async_status = UWSGI_OK; // check here @@ -171,7 +186,7 @@ static void u_green_request(struct wsgi_request *wsgi_req, int async_id) { while(wsgi_req->async_status == UWSGI_AGAIN) { u_green_schedule_to_main(async_id); - wsgi_req->async_status = uwsgi.shared->hook_request[wsgi_req->uh.modifier1](wsgi_req); + wsgi_req->async_status = uwsgi.p[wsgi_req->uh.modifier1]->request(wsgi_req); } u_green_schedule_to_main(async_id); @@ -182,23 +197,23 @@ static void u_green_request(struct wsgi_request *wsgi_req, int async_id) { } -void u_green_init() { +int u_green_init() { struct wsgi_request *wsgi_req; volatile int i; - uwsgi.u_stack_size = UGREEN_DEFAULT_STACKSIZE; + ug.u_stack_size = UGREEN_DEFAULT_STACKSIZE; - if (uwsgi.ugreen_stackpages > 0) { - uwsgi.u_stack_size = uwsgi.ugreen_stackpages * uwsgi.page_size; + if (ug.stackpages > 0) { + ug.u_stack_size = ug.stackpages * uwsgi.page_size; } - uwsgi_log("initializing %d uGreen threads with stack size of %lu (%lu KB)\n", uwsgi.async, (unsigned long) uwsgi.u_stack_size, (unsigned long) uwsgi.u_stack_size/1024); + uwsgi_log("initializing %d uGreen threads with stack size of %lu (%lu KB)\n", uwsgi.async, (unsigned long) ug.u_stack_size, (unsigned long) ug.u_stack_size/1024); - uwsgi.ugreen_contexts = malloc( sizeof(ucontext_t*) * uwsgi.async); - if (!uwsgi.ugreen_contexts) { + ug.contexts = malloc( sizeof(ucontext_t*) * uwsgi.async); + if (!ug.contexts) { uwsgi_error("malloc()\n"); exit(1); } @@ -206,38 +221,40 @@ void u_green_init() { for(i=0;iuc_stack.ss_sp = mmap(NULL, uwsgi.u_stack_size + (uwsgi.page_size*2) , PROT_READ | PROT_WRITE | PROT_EXEC, MAP_ANON | MAP_PRIVATE, -1, 0) + uwsgi.page_size; + getcontext(ug.contexts[i]); + ug.contexts[i]->uc_stack.ss_sp = mmap(NULL, ug.u_stack_size + (uwsgi.page_size*2) , PROT_READ | PROT_WRITE | PROT_EXEC, MAP_ANON | MAP_PRIVATE, -1, 0) + uwsgi.page_size; - if (!uwsgi.ugreen_contexts[i]->uc_stack.ss_sp) { + if (!ug.contexts[i]->uc_stack.ss_sp) { uwsgi_error("mmap()"); exit(1); } // set guard pages for stack - if (mprotect(uwsgi.ugreen_contexts[i]->uc_stack.ss_sp - uwsgi.page_size, uwsgi.page_size, PROT_NONE)) { + if (mprotect(ug.contexts[i]->uc_stack.ss_sp - uwsgi.page_size, uwsgi.page_size, PROT_NONE)) { uwsgi_error("mprotect()"); exit(1); } - if (mprotect(uwsgi.ugreen_contexts[i]->uc_stack.ss_sp + uwsgi.u_stack_size, uwsgi.page_size, PROT_NONE)) { + if (mprotect(ug.contexts[i]->uc_stack.ss_sp + ug.u_stack_size, uwsgi.page_size, PROT_NONE)) { uwsgi_error("mprotect()"); exit(1); } - uwsgi.ugreen_contexts[i]->uc_stack.ss_size = uwsgi.u_stack_size; - uwsgi.ugreen_contexts[i]->uc_link = NULL; - makecontext(uwsgi.ugreen_contexts[i], (void (*) (void)) &u_green_request, 2, wsgi_req, i); + ug.contexts[i]->uc_stack.ss_size = ug.u_stack_size; + ug.contexts[i]->uc_link = NULL; + makecontext(ug.contexts[i], u_green_request, 2, wsgi_req, i); wsgi_req->async_status = UWSGI_ACCEPTING; wsgi_req->async_id = i; - uwsgi_log("wsgi_req %d %d\n", wsgi_req->async_id, wsgi_req->async_status); + uwsgi_log("wsgi_req %d %d %p\n", wsgi_req->async_id, wsgi_req->async_status, ug.contexts[i]); } uwsgi_register_loop("ugreen", u_green_loop); + return 0; + } void u_green_expire_timeouts() { @@ -294,8 +311,17 @@ void u_green_loop() { int i, current = 0, timeout; + for(i=0;iasync_status = UWSGI_ACCEPTING; + wsgi_req->async_id = i; + } + + uwsgi_log("FFAR: %p\n", find_first_accepting_wsgi_req()); + while(uwsgi.workers[uwsgi.mywid].manage_next_request) { + //uwsgi_log("i am uGreen...\n"); uwsgi.async_running = u_green_blocking(); timeout = u_green_get_timeout(); @@ -309,8 +335,10 @@ void u_green_loop() { for(i=0; iasync_id); u_green_schedule_to_req(wsgi_req); @@ -345,12 +373,19 @@ cycle: } -case LONG_ARGS_UGREEN_PAGES: - uwsgi.ugreen_stackpages = atoi(optarg); - return 1; +int uwsgi_ugreen_manage_opt(int i, char *optarg) { -struct uwsgi_plugin ugreen_plugin { + switch(i) { + case LONG_ARGS_UGREEN_PAGES: + ug.stackpages = atoi(optarg); + return 1; + } + + return 0; +} + +struct uwsgi_plugin ugreen_plugin = { .name = "ugreen", .init = u_green_init, -} +}; diff --git a/plugins/ugreen/uwsgiplugin.py b/plugins/ugreen/uwsgiplugin.py index 94ae122e..b206c620 100644 --- a/plugins/ugreen/uwsgiplugin.py +++ b/plugins/ugreen/uwsgiplugin.py @@ -1,6 +1,7 @@ NAME='ugreen' -CFLAGS = ['-D_XOPEN_SOURCE'] +CFLAGS = [] LDFLAGS = [] +LIBS = [] GCC_LIST = ['ugreen'] diff --git a/uwsgi.c b/uwsgi.c index 48d13e9f..9a1c8957 100644 --- a/uwsgi.c +++ b/uwsgi.c @@ -1362,6 +1362,7 @@ uwsgi.shared->hooks[UWSGI_MODIFIER_PING] = uwsgi_request_ping; //100 void (*u_loop) (void) = uwsgi_get_loop(uwsgi.loop); uwsgi_log("running %s loop %p\n", uwsgi.loop, u_loop); u_loop(); + uwsgi_log("done\n"); goto end; } else { if (uwsgi.threads > 1) {