diff --git a/plugins/psgi/psgi.h b/plugins/psgi/psgi.h index 9eab8f0b..4b80a09d 100644 --- a/plugins/psgi/psgi.h +++ b/plugins/psgi/psgi.h @@ -37,6 +37,9 @@ struct uwsgi_perl { CV **tmp_psgix_logger; CV **tmp_stream_responder; + + SV *postfork; + SV *atexit; }; void init_perl_embedded_module(void); @@ -52,3 +55,4 @@ int uwsgi_perl_obj_isa(SV *, char *); int init_psgi_app(struct wsgi_request *, char *, uint16_t, PerlInterpreter **); PerlInterpreter *uwsgi_perl_new_interpreter(void); int uwsgi_perl_mule(char *); +void uwsgi_perl_run_hook(SV *); diff --git a/plugins/psgi/psgi_plugin.c b/plugins/psgi/psgi_plugin.c index 0f47d4db..89156a5d 100644 --- a/plugins/psgi/psgi_plugin.c +++ b/plugins/psgi/psgi_plugin.c @@ -557,6 +557,10 @@ void uwsgi_perl_post_fork() { sv_setiv(GvSV(tmpgv), (IV)getpid()); SvREADONLY_on(GvSV(tmpgv)); } + + if (uperl.postfork) { + uwsgi_perl_run_hook(uperl.postfork); + } } int uwsgi_perl_mount_app(char *mountpoint, char *app) { @@ -624,6 +628,51 @@ int uwsgi_perl_signal_handler(uint8_t sig, void *handler) { return ret; } +void uwsgi_perl_run_hook(SV *hook) { + dSP; + ENTER; + SAVETMPS; + PUSHMARK(SP); + XPUSHs( hook ); + PUTBACK; + + call_sv( SvRV(hook), G_DISCARD); + + if(SvTRUE(ERRSV)) { + uwsgi_log("[uwsgi-perl error] %s\n", SvPV_nolen(ERRSV)); + return; + } + + SPAGAIN; + PUTBACK; + FREETMPS; + LEAVE; +} + +static void uwsgi_perl_atexit() { + if (uwsgi.mywid == -1) goto realstuff; + + // if hijacked do not run atexit hooks + if (uwsgi.workers[uwsgi.mywid].hijacked) + return; + + // if busy do not run atexit hooks + if (uwsgi.workers[uwsgi.mywid].busy) + return; + +#ifdef UWSGI_ASYNC + // managing atexit in async mode is a real pain...skip it for now + if (uwsgi.async > 1) + return; +#endif + +realstuff: + + if (uperl.atexit) { + uwsgi_perl_run_hook(uperl.atexit); + } +} + struct uwsgi_plugin psgi_plugin = { .name = "psgi", @@ -644,5 +693,7 @@ struct uwsgi_plugin psgi_plugin = { .after_request = uwsgi_perl_after_request, .enable_threads = uwsgi_perl_enable_threads, + .atexit = uwsgi_perl_atexit, + .magic = uwsgi_perl_magic, }; diff --git a/plugins/psgi/uwsgi_plmodule.c b/plugins/psgi/uwsgi_plmodule.c index d95ca141..0c7ec768 100644 --- a/plugins/psgi/uwsgi_plmodule.c +++ b/plugins/psgi/uwsgi_plmodule.c @@ -2,6 +2,7 @@ extern struct uwsgi_server uwsgi; extern struct uwsgi_plugin psgi_plugin; +extern struct uwsgi_perl uperl; #ifdef UWSGI_ASYNC @@ -171,6 +172,28 @@ XS(XS_register_signal) { } +XS(XS_postfork) { + dXSARGS; + + psgi_check_args(1); + + uperl.postfork = newRV_inc(ST(0)); + + XSRETURN_YES; +} + +XS(XS_atexit) { + dXSARGS; + + psgi_check_args(1); + + uperl.atexit = newRV_inc(ST(0)); + + XSRETURN_YES; +} + + + XS(XS_log) { dXSARGS; @@ -282,5 +305,7 @@ void init_perl_embedded_module() { psgi_xs(signal); psgi_xs(register_signal); psgi_xs(signal_wait); + psgi_xs(postfork); + psgi_xs(atexit); } diff --git a/test.psgi b/test.psgi index fdc58d84..bbbf76ef 100644 --- a/test.psgi +++ b/test.psgi @@ -55,3 +55,11 @@ my $app = sub { [ "Hello World\r\n", $env->{'REQUEST_URI'}, uwsgi::cache_get('key1'), uwsgi::call('hello') ], ]; }; + +uwsgi::postfork(sub { + print "forked !!!\n"; +}); + +uwsgi::atexit(sub { + print "exited\n"; +});