diff --git a/loop.c b/loop.c index d5eb109d..91822028 100644 --- a/loop.c +++ b/loop.c @@ -52,7 +52,7 @@ void *simple_loop(void *arg1) { pthread_sigmask(SIG_BLOCK, &smask, NULL); for(i=0;i<0xFF;i++) { if (uwsgi.p[i]->init_thread) { - uwsgi.p[i]->init_thread(); + uwsgi.p[i]->init_thread(core_id); } } /* diff --git a/plugins/psgi/psgi_plugin.c b/plugins/psgi/psgi_plugin.c index e412b20d..8a19264d 100644 --- a/plugins/psgi/psgi_plugin.c +++ b/plugins/psgi/psgi_plugin.c @@ -1,21 +1,22 @@ -#include +#include "../../uwsgi.h" #include #include -static PerlInterpreter *my_perl; -static SV *psgi_func; - -#ifdef UWSGI_THREADING -pthread_key_t uwsgi_perl_interpreter; -#endif extern char **environ; extern struct uwsgi_server uwsgi; struct uwsgi_perl { + int fd; + char *psgibuffer; char *psgi; + PerlInterpreter *main; + pthread_key_t u_interpreter; + PerlInterpreter **interp; + SV *psgi_main; + SV **psgi_func; } uperl; @@ -97,8 +98,6 @@ xs_init(pTHX) int uwsgi_perl_init(){ - char *psgibuffer; - int fd; struct stat stat_psgi; @@ -109,91 +108,131 @@ int uwsgi_perl_init(){ uwsgi_log("initializing Perl environment\n"); PERL_SYS_INIT3(&argc, (char ***) &embedding, &environ); - my_perl = perl_alloc(); - if (!my_perl) { + uperl.main = perl_alloc(); + if (!uperl.main) { uwsgi_log("unable to allocate perl interpreter\n"); return -1; } - PL_perl_destruct_level = 1; - perl_construct(my_perl); + dTHXa(uperl.main); + PERL_SET_CONTEXT(uperl.main); + + PL_perl_destruct_level = 2; + perl_construct(uperl.main); // filling http status codes for (http_sc = hsc; http_sc->message != NULL; http_sc++) { http_sc->message_size = strlen(http_sc->message); } -#ifdef UWSGI_THREADING - if (uwsgi.threads > 1) { - if (pthread_key_create(&uwsgi_perl_interpreter, NULL)) { - uwsgi_error("pthread_key_create()"); - exit(1); - } - } -#endif - PL_origalen = 1; - perl_parse(my_perl, xs_init, 4, embedding, NULL); + perl_parse(uperl.main, xs_init, 4, embedding, NULL); perl_eval_pv("use IO::Handle;", 0); - fd = open(uperl.psgi, O_RDONLY); - if (fd < 0) { + uperl.fd = open(uperl.psgi, O_RDONLY); + if (uperl.fd < 0) { uwsgi_error("open()"); goto clear; } - if (fstat(fd, &stat_psgi)) { + if (fstat(uperl.fd, &stat_psgi)) { uwsgi_error("fstat()"); - close(fd); + close(uperl.fd); goto clear; } - psgibuffer = malloc(stat_psgi.st_size + 1); - if (!psgibuffer) { + uperl.psgibuffer = malloc(stat_psgi.st_size + 1); + if (!uperl.psgibuffer) { uwsgi_error("malloc()"); - close(fd); + close(uperl.fd); goto clear; } - if (read(fd, psgibuffer, stat_psgi.st_size) != stat_psgi.st_size) { + if (read(uperl.fd, uperl.psgibuffer, stat_psgi.st_size) != stat_psgi.st_size) { uwsgi_error("read()"); - close(fd); - free(psgibuffer); + close(uperl.fd); + free(uperl.psgibuffer); goto clear; } - psgibuffer[stat_psgi.st_size] = 0; + uperl.psgibuffer[stat_psgi.st_size] = 0; - psgi_func = perl_eval_pv(psgibuffer, 0); + if (uwsgi.threads < 2) { + uperl.psgi_main = perl_eval_pv(uperl.psgibuffer, 0); + if (!uperl.psgi_main) { + uwsgi_log("unable to find PSGI function entry point.\n"); + close(uperl.fd); + free(uperl.psgibuffer); + goto clear; + } - if (!psgi_func) { - uwsgi_log("unable to find PSGI function entry point.\n"); - close(fd); - free(psgibuffer); - goto clear; + if(SvTRUE(ERRSV)) { + uwsgi_log("%s\n", SvPV_nolen(ERRSV)); + goto clear; + } + + free(uperl.psgibuffer); + close(uperl.fd); } - if(SvTRUE(ERRSV)) { - uwsgi_log("%s\n", SvPV_nolen(ERRSV)); - goto clear; - } - - uwsgi_log("PSGI_FUNC %p\n", psgi_func); - - free(psgibuffer); - close(fd); - return 0; clear: uwsgi_log("error initializing the perl engine\n"); - perl_destruct(my_perl); - perl_free(my_perl); + perl_destruct(uperl.main); + perl_free(uperl.main); return -1; } +void uwsgi_perl_enable_threads() { + + int i; + + if (pthread_key_create(&uperl.u_interpreter, NULL)) { + uwsgi_error("pthread_key_create()"); + exit(1); + } + + uperl.interp = malloc( sizeof(PerlInterpreter*) * uwsgi.threads ); + if (!uperl.interp) { + uwsgi_error("malloc()"); + exit(1); + } + + for(i=1;iuh.pktsize) { uwsgi_log("Invalid PSGI request. skip.\n"); @@ -222,6 +266,13 @@ int uwsgi_perl_request(struct wsgi_request *wsgi_req) { } +#ifdef UWSGI_THREADING + if (uwsgi.threads > 1 && wsgi_req->async_id > 0) { + psgi_func = uperl.psgi_func[wsgi_req->async_id]; + my_perl = pthread_getspecific(uperl.u_interpreter); + } +#endif + dSP; ENTER; @@ -271,12 +322,14 @@ int uwsgi_perl_request(struct wsgi_request *wsgi_req) { SPAGAIN; + SV *pi = SvREFCNT_inc(POPs); item = hv_store(env, "psgi.input", 10, pi, 0); + PUSHMARK(SP); XPUSHs( newSVpv( "IO::Handle", 10 )); PUTBACK; @@ -297,6 +350,7 @@ int uwsgi_perl_request(struct wsgi_request *wsgi_req) { item = hv_store(env, "psgi.errors", 11, pe, 0); + PUSHMARK(SP); XPUSHs( sv_2mortal(newRV((SV *)env )) ); PUTBACK; @@ -437,7 +491,25 @@ void uwsgi_perl_after_request(struct wsgi_request *wsgi_req) { log_request(wsgi_req); } -void uwsgi_perl_init_thread() { +void uwsgi_perl_init_thread(int core_id) { + + + pthread_setspecific(uperl.u_interpreter, uperl.interp[core_id]); + dTHXa(uperl.interp[core_id]); + PERL_SET_CONTEXT(uperl.interp[core_id]); + + uperl.psgi_func[core_id] = perl_eval_pv(uperl.psgibuffer, 0); + if (!uperl.psgi_func[core_id]) { + uwsgi_log("unable to find PSGI function entry point.\n"); + exit(1); + } + + if(SvTRUE(ERRSV)) { + uwsgi_log("%s\n", SvPV_nolen(ERRSV)); + exit(1); + } + + } int uwsgi_perl_manage_options(int i, char *optarg) { @@ -460,6 +532,7 @@ struct uwsgi_plugin psgi_plugin = { .options = uwsgi_perl_options, //.magic = uwsgi_perl_magic, //.help = uwsgi_perl_help, + .enable_threads = uwsgi_perl_enable_threads, .manage_opt = uwsgi_perl_manage_options, .init_thread = uwsgi_perl_init_thread, .request = uwsgi_perl_request, diff --git a/plugins/python/python_plugin.c b/plugins/python/python_plugin.c index 8eb66492..2b0455a8 100644 --- a/plugins/python/python_plugin.c +++ b/plugins/python/python_plugin.c @@ -591,7 +591,7 @@ void uwsgi_uwsgi_config(char *module) { uwsgi_log("threads support enabled\n"); } - void uwsgi_python_init_thread() { + void uwsgi_python_init_thread(int core_id) { // set a new ThreadState for each thread PyThreadState *pts; diff --git a/plugins/rack/rack_plugin.c b/plugins/rack/rack_plugin.c index 140a9fd5..975f72f2 100644 --- a/plugins/rack/rack_plugin.c +++ b/plugins/rack/rack_plugin.c @@ -752,7 +752,7 @@ void uwsgi_rack_enable_threads(void) { pthread_mutex_init(&ur.gvl, NULL); } -void uwsgi_rack_init_thread(void) { +void uwsgi_rack_init_thread(int core_id) { // thread initialization } diff --git a/uwsgi.h b/uwsgi.h index c96db567..9c3429fc 100644 --- a/uwsgi.h +++ b/uwsgi.h @@ -348,7 +348,7 @@ struct uwsgi_plugin { int (*manage_opt) (int, char *); void (*magic) (char *); void (*enable_threads) (void); - void (*init_thread) (void); + void (*init_thread) (int); int (*request) (struct wsgi_request *); void (*after_request) (struct wsgi_request *); void (*init_apps) (void); diff --git a/uwsgiconfig.py b/uwsgiconfig.py index 6eebbf5d..c35ff446 100644 --- a/uwsgiconfig.py +++ b/uwsgiconfig.py @@ -170,6 +170,12 @@ class uConf(): def get_gcll(self): kvm_list = ['FreeBSD', 'OpenBSD', 'NetBSD', 'DragonFly'] + if uwsgi_os == 'Darwin': + # build a universal binary on osx + self.cflags.append('-arch i386') + self.cflags.append('-arch x86_64') + self.cflags.append('-arch ppc') + if uwsgi_os == 'SunOS': self.libs.append('-lsendfile') self.libs.remove('-rdynamic')