diff --git a/core/gateway.c b/core/gateway.c index a9c72db1..d1a6c16c 100644 --- a/core/gateway.c +++ b/core/gateway.c @@ -41,6 +41,10 @@ struct uwsgi_gateway *register_gateway(char *name, void (*loop) (int, void *), v return ug; } +static void gateway_brutal_end() { + _exit(UWSGI_END_CODE); +} + void gateway_respawn(int id) { pid_t gw_pid; @@ -65,6 +69,7 @@ void gateway_respawn(int id) { } #endif uwsgi.mypid = getpid(); + atexit(gateway_brutal_end); signal(SIGALRM, SIG_IGN); signal(SIGHUP, SIG_IGN); signal(SIGINT, end_me); diff --git a/core/routing.c b/core/routing.c index 1fe55d5c..7dc5c624 100644 --- a/core/routing.c +++ b/core/routing.c @@ -734,6 +734,7 @@ struct uwsgi_route_condition *uwsgi_register_route_condition(char *name, int (*f void uwsgi_routing_dump() { struct uwsgi_route *routes = uwsgi.routes; + if (!routes) return; uwsgi_log("*** dumping internal routing table ***\n"); while(routes) { if (routes->label) { diff --git a/core/rpc.c b/core/rpc.c index dc8efdc6..6aaa5070 100644 --- a/core/rpc.c +++ b/core/rpc.c @@ -15,9 +15,13 @@ int uwsgi_register_rpc(char *name, uint8_t modifier1, uint8_t args, void *func) uwsgi_lock(uwsgi.rpc_table_lock); if (uwsgi.shared->rpc_count < uwsgi.rpc_max) { + uwsgi_log("rpc_max = %d %d\n", uwsgi.rpc_max, uwsgi.shared->rpc_count); urpc = &uwsgi.rpc_table[uwsgi.shared->rpc_count]; + uwsgi_log("rpc_max = %d\n", uwsgi.rpc_max); + uwsgi_log("NAME = %s %d %p\n", name, strlen(name), urpc->name); memcpy(urpc->name, name, strlen(name)); + uwsgi_log("NAME = %s\n", name); urpc->modifier1 = modifier1; urpc->args = args; urpc->func = func; @@ -69,7 +73,7 @@ char *uwsgi_do_rpc(char *node, char *func, uint8_t argc, char *argv[], uint16_t if (node == NULL || !strcmp(node, "")) { // allocate the whole buffer - buffer = uwsgi_malloc(65536); + buffer = uwsgi_malloc(UMAX16); *len = uwsgi_rpc(func, argc, argv, argvs, buffer); return buffer; } @@ -145,5 +149,6 @@ error: void uwsgi_rpc_init() { + uwsgi_log("ALLOCATE\n"); uwsgi.rpc_table = uwsgi_calloc_shared(sizeof(struct uwsgi_rpc) * uwsgi.rpc_max); } diff --git a/core/signal.c b/core/signal.c index f9dd0b2b..ff1eaee9 100644 --- a/core/signal.c +++ b/core/signal.c @@ -96,6 +96,8 @@ int uwsgi_register_signal(uint8_t sig, char *receiver, void *handler, uint8_t mo struct uwsgi_signal_entry *use = NULL; + if (!uwsgi.master_process) return -1; + if (strlen(receiver) > 63) return -1; diff --git a/core/uwsgi.c b/core/uwsgi.c index f73539a9..3f7c33eb 100644 --- a/core/uwsgi.c +++ b/core/uwsgi.c @@ -2167,6 +2167,9 @@ int uwsgi_start(void *v_argv) { // setup locking uwsgi_setup_locking(); + // allocate rpc structures + uwsgi_rpc_init(); + // setup sharedarea if (uwsgi.sharedareasize > 0) { uwsgi.sharedarea = uwsgi_calloc_shared(uwsgi.page_size * uwsgi.sharedareasize); @@ -2393,9 +2396,6 @@ unsafe: } } - // allocate rpc structures - uwsgi_rpc_init(); - // set masterpid uwsgi.mypid = getpid(); masterpid = uwsgi.mypid; diff --git a/plugins/jvm/jvm.h b/plugins/jvm/jvm.h index 811347e3..4419e652 100644 --- a/plugins/jvm/jvm.h +++ b/plugins/jvm/jvm.h @@ -11,12 +11,23 @@ struct uwsgi_jvm { struct uwsgi_string_list *main_classes; jclass str_class; + jclass runtime_exception; + + jmethodID api_signal_handler_mid; + jmethodID api_rpc_function_mid; }; jclass uwsgi_jvm_class(char *); jobject uwsgi_jvm_ref(jobject); void uwsgi_jvm_unref(jobject); -int uwsgi_jvm_call_static(jclass, jmethodID); +int uwsgi_jvm_call_static(jclass, jmethodID, ...); +int uwsgi_jvm_call(jobject, jmethodID, ...); void uwsgi_jvm_clear_exception(void); +char *uwsgi_jvm_str2c(jobject); + +void uwsgi_jvm_throw(char *); + +jobject uwsgi_jvm_call_objectA(jobject o, jmethodID mid, jvalue *); +void uwsgi_jvm_release_chars(jobject, char *); diff --git a/plugins/jvm/jvm_plugin.c b/plugins/jvm/jvm_plugin.c index 07a23bb1..977ef6cd 100644 --- a/plugins/jvm/jvm_plugin.c +++ b/plugins/jvm/jvm_plugin.c @@ -10,18 +10,30 @@ This plugin is the core for all of the JVM-based ones */ extern struct uwsgi_server uwsgi; +struct uwsgi_plugin jvm_plugin; -JNIEXPORT jint JNICALL uwsgi_jvm_api_worker_id(JNIEnv *env) { +JNIEXPORT jint JNICALL uwsgi_jvm_api_worker_id(JNIEnv *env, jclass c) { return uwsgi.mywid; } -JNIEXPORT void JNICALL uwsgi_jvm_api_hello(JNIEnv *env, jclass c) { - uwsgi_log("AAAA\n"); +JNIEXPORT void JNICALL uwsgi_jvm_api_register_signal(JNIEnv *env, jclass c, jint signum, jstring target, jobject handler) { + char *t = uwsgi_jvm_str2c(target); + if (uwsgi_register_signal(signum, t, uwsgi_jvm_ref(handler), jvm_plugin.modifier1)) { + uwsgi_jvm_throw("unable to register signal handler"); + } +} + +JNIEXPORT void JNICALL uwsgi_jvm_api_register_rpc(JNIEnv *env, jclass c, jstring name, jobject func) { + char *n = uwsgi_jvm_str2c(name); + if (uwsgi_register_rpc(n, jvm_plugin.modifier1, 0, uwsgi_jvm_ref(func))) { + uwsgi_jvm_throw("unable to register rpc function"); + } } static JNINativeMethod uwsgi_jvm_api_methods[] = { + {"register_signal", "(ILjava/lang/String;Luwsgi$SignalHandler;)V", (void *) &uwsgi_jvm_api_register_signal}, + {"register_rpc", "(Ljava/lang/String;Luwsgi$RpcFunction;)V", (void *) &uwsgi_jvm_api_register_rpc}, {"worker_id", "()I", (void *) &uwsgi_jvm_api_worker_id}, - {"hello", "()V", (void *) &uwsgi_jvm_api_hello}, }; struct uwsgi_jvm ujvm; @@ -59,6 +71,7 @@ jclass uwsgi_jvm_class(char *name) { return NULL; } + return my_class; return uwsgi_jvm_ref(my_class); } @@ -73,7 +86,7 @@ jmethodID uwsgi_jvm_get_static_method_id(jclass cls, char *name, char *signature } jobject uwsgi_jvm_ref(jobject obj) { - return (*ujvm.env)->NewLocalRef(ujvm.env, obj); + return (*ujvm.env)->NewGlobalRef(ujvm.env, obj); } void uwsgi_jvm_unref(jobject obj) { @@ -91,14 +104,37 @@ jobject uwsgi_jvm_str(char *str, size_t len) { new_str = (*ujvm.env)->NewStringUTF(ujvm.env, str); } - return uwsgi_jvm_ref(new_str); + return new_str; } -int uwsgi_jvm_call_static(jclass c, jmethodID mid) { - (*ujvm.env)->CallStaticVoidMethod(ujvm.env, c, mid); +int uwsgi_jvm_call_static(jclass c, jmethodID mid, ...) { + va_list args; + va_start(args, mid); + (*ujvm.env)->CallStaticVoidMethod(ujvm.env, c, mid, args); + va_end(args); return uwsgi_jvm_exception(); } +int uwsgi_jvm_call(jobject o, jmethodID mid, ...) { + va_list args; + va_start(args, mid); + (*ujvm.env)->CallVoidMethodV(ujvm.env, o, mid, args); + va_end(args); + return uwsgi_jvm_exception(); +} + +jobject uwsgi_jvm_call_objectA(jobject o, jmethodID mid, jvalue *args) { + jobject ret = (*ujvm.env)->CallObjectMethodA(ujvm.env, o, mid, args); + if (uwsgi_jvm_exception()) { + return NULL; + } + return ret; +} + +void uwsgi_jvm_throw(char *message) { + (*ujvm.env)->ThrowNew(ujvm.env, ujvm.runtime_exception, message); +} + static int uwsgi_jvm_init(void) { JavaVM *jvm; @@ -146,6 +182,12 @@ static int uwsgi_jvm_init(void) { uwsgi_log("JVM initialized at %p\n", ujvm.env); } + ujvm.str_class = uwsgi_jvm_class("java/lang/String"); + if (!ujvm.str_class) exit(1); + + ujvm.runtime_exception = uwsgi_jvm_class("java/lang/RuntimeException"); + if (!ujvm.runtime_exception) exit(1); + jclass uwsgi_class = uwsgi_jvm_class("uwsgi"); if (!uwsgi_class) { exit(1); @@ -155,6 +197,16 @@ static int uwsgi_jvm_init(void) { exit(1); } + jclass uwsgi_signal_handler_class = uwsgi_jvm_class("uwsgi$SignalHandler"); + if (!uwsgi_signal_handler_class) exit(1); + ujvm.api_signal_handler_mid = uwsgi_jvm_get_method_id(uwsgi_signal_handler_class, "function", "(I)V"); + if (!ujvm.api_signal_handler_mid) exit(1); + + jclass uwsgi_rpc_function_class = uwsgi_jvm_class("uwsgi$RpcFunction"); + if (!uwsgi_rpc_function_class) exit(1); + ujvm.api_rpc_function_mid = uwsgi_jvm_get_method_id(uwsgi_rpc_function_class, "function", "([Ljava/lang/String;)Ljava/lang/String;"); + if (!ujvm.api_rpc_function_mid) exit(1); + struct uwsgi_string_list *usl = ujvm.main_classes; while(usl) { jclass c = uwsgi_jvm_class(usl->value); @@ -175,23 +227,7 @@ static int uwsgi_jvm_init(void) { } usl = usl->next; } -/* - if (ujvm.class) { - ujvm.main_class = uwsgi_jvm_get_class(ujvm.class); - if (!ujvm.main_class) { - exit(1); - } - mmid = uwsgi_jvm_get_static_method_id(ujvm.main_class, "main", "([Ljava/lang/String;)V"); - if (mmid) { - (*ujvm.env)->CallStaticVoidMethod(ujvm.env, ujvm.main_class, mmid); - uwsgi_jvm_exception(); - } - } - - ujvm.str_class = uwsgi_jvm_get_class("java/lang/String"); - ujvm.ht_class = uwsgi_jvm_get_class("java/util/Hashtable"); -*/ return 1; @@ -207,10 +243,55 @@ size_t uwsgi_jvm_strlen(jobject obj) { return (*ujvm.env)->GetStringUTFLength(ujvm.env, obj); } +static int uwsgi_jvm_signal_handler(uint8_t signum, void *handler) { + long l_signum = signum; + return uwsgi_jvm_call(handler, ujvm.api_signal_handler_mid, (void *) l_signum); +} + +// route request to the specific JVM plugin (identified by modifier2) +static int uwsgi_jvm_request(struct wsgi_request *wsgi_req) { + return UWSGI_OK; +} + +void uwsgi_jvm_release_chars(jobject o, char *str) { + (*ujvm.env)->ReleaseStringUTFChars(ujvm.env, o, str); +} + +static uint16_t uwsgi_jvm_rpc(void *func, uint8_t argc, char **argv, uint16_t argvs[], char *buffer) { + jvalue *args = uwsgi_calloc(sizeof(jvalue) * argc+1); + uint8_t i; + for(i=0;iDeleteLocalRef(ujvm.env, ret); + return rlen; + } +end: + (*ujvm.env)->DeleteLocalRef(ujvm.env, ret); + return 0; +} + struct uwsgi_plugin jvm_plugin = { .name = "jvm", + .modifier1 = 8, + + .request = uwsgi_jvm_request, + .init = uwsgi_jvm_init, .options = uwsgi_jvm_options, + + .signal_handler = uwsgi_jvm_signal_handler, + .rpc = uwsgi_jvm_rpc, }; diff --git a/plugins/mono/mono_plugin.c b/plugins/mono/mono_plugin.c index 08a71ee3..30bf3d0a 100644 --- a/plugins/mono/mono_plugin.c +++ b/plugins/mono/mono_plugin.c @@ -540,7 +540,7 @@ static void uwsgi_mono_enable_threads(void) { static void uwsgi_mono_post_fork() { - // yes, ono is not fork-friendly, so we initialize it in the post_fork hook + // yes, Mono is not fork-friendly, so we initialize it in the post_fork hook uwsgi_mono_init_apps(); MonoMethodDesc *desc = mono_method_desc_new("uwsgi.api:RunPostForkHook()", 1); diff --git a/plugins/rpc/rpc_plugin.c b/plugins/rpc/rpc_plugin.c index c592c101..b84d5549 100644 --- a/plugins/rpc/rpc_plugin.c +++ b/plugins/rpc/rpc_plugin.c @@ -1,16 +1,18 @@ -#include "../../uwsgi.h" +#include extern struct uwsgi_server uwsgi; -int uwsgi_rpc_request(struct wsgi_request *wsgi_req) { +static int uwsgi_rpc_request(struct wsgi_request *wsgi_req) { // this is the list of args - char *argv[256]; + char *argv[UMAX8]; // this is the size of each argument - uint16_t argvs[256]; + uint16_t argvs[UMAX8]; // maximum number of supported arguments uint8_t argc = 0xff; + // response output + char response_buf[UMAX16]; /* Standard RPC request */ if (!wsgi_req->uh->pktsize) { @@ -18,38 +20,24 @@ int uwsgi_rpc_request(struct wsgi_request *wsgi_req) { return -1; } - /* - for(argc=0;argcuh.pktsize;argc++) { - uwsgi_log("rpc: %c\n", wsgi_req->buffer[argc]); - } - */ - -#ifdef UWSGI_DEBUG - uwsgi_log("RPC pktsize %d\n", wsgi_req->uh->pktsize); -#endif - if (uwsgi_parse_array(wsgi_req->buffer, wsgi_req->uh->pktsize, argv, argvs, &argc)) { uwsgi_log("Invalid RPC request. skip.\n"); return -1; } -#ifdef UWSGI_DEBUG - uwsgi_log("RPC args %d\n", argc-1); -#endif - // call the function (output will be in wsgi_req->buffer) - wsgi_req->uh->pktsize = uwsgi_rpc(argv[0], argc-1, argv+1, argvs+1, wsgi_req->buffer); + wsgi_req->uh->pktsize = uwsgi_rpc(argv[0], argc-1, argv+1, argvs+1, response_buf); - // using modifier1 we may want a raw output + // using modifier2 we may want a raw output if (wsgi_req->uh->modifier2 == 0) { if (uwsgi_response_write_body_do(wsgi_req, (char *) wsgi_req->uh, 4)) { return -1; } } // write the response - uwsgi_response_write_body_do(wsgi_req, wsgi_req->buffer, wsgi_req->uh->pktsize); + uwsgi_response_write_body_do(wsgi_req, response_buf, wsgi_req->uh->pktsize); - return 0; + return UWSGI_OK; } struct uwsgi_plugin rpc_plugin = { diff --git a/uwsgi.h b/uwsgi.h index 51a248bf..40565672 100644 --- a/uwsgi.h +++ b/uwsgi.h @@ -7,6 +7,7 @@ extern "C" { #endif #define UMAX16 65536 +#define UMAX8 256 #define UMAX64_STR "18446744073709551616" @@ -2239,7 +2240,7 @@ struct uwsgi_server { }; struct uwsgi_rpc { - char name[0xff]; + char name[UMAX8]; void *func; uint8_t args; uint8_t modifier1;