diff --git a/config30.ru b/config30.ru index 8dd71257..34bb6cb0 100644 --- a/config30.ru +++ b/config30.ru @@ -32,6 +32,14 @@ postfork do puts "fork() called" end +rpc 'pippo' do + "i am an rpc function" +end + +rpc 'pluto' do |x,y| + "i am another rpc function #{x} #{y}" +end + begin foo_func rescue diff --git a/plugins/python/python_plugin.c b/plugins/python/python_plugin.c index 48c56996..1467a286 100644 --- a/plugins/python/python_plugin.c +++ b/plugins/python/python_plugin.c @@ -1263,7 +1263,7 @@ uint16_t uwsgi_python_rpc(void *func, uint8_t argc, char **argv, char *buffer) { if (ret) { if (PyString_Check(ret)) { rv = PyString_AsString(ret); - rl = strlen(rv); + rl = PyString_Size(ret); if (rl <= 0xffff) { memcpy(buffer, rv, rl); Py_DECREF(ret); diff --git a/plugins/rack/rack_plugin.c b/plugins/rack/rack_plugin.c index df550d19..8ccf0a71 100644 --- a/plugins/rack/rack_plugin.c +++ b/plugins/rack/rack_plugin.c @@ -195,6 +195,29 @@ VALUE uwsgi_ruby_signal_registered(VALUE *class, VALUE signum) { return Qfalse; } +VALUE uwsgi_ruby_register_rpc(int argc, VALUE *argv, VALUE *class) { + + int rb_argc = 0; + + if (argc < 2) goto clear; + if (argc > 2) { + rb_argc = NUM2INT(argv[2]); + } + char *name = RSTRING_PTR(argv[0]); + void *func = (void *) argv[1]; + + + if (uwsgi_register_rpc(name, 7, rb_argc, func)) { +clear: + rb_raise(rb_eRuntimeError, "unable to register rpc function"); + return Qnil; + } + rb_gc_register_address(&argv[1]); + rb_ary_push(ur.rpc_protector, argv[1]); + + return Qtrue; +} + VALUE uwsgi_ruby_register_signal(VALUE *class, VALUE signum, VALUE sigkind, VALUE rbhandler) { @@ -261,6 +284,50 @@ int uwsgi_rack_signal_handler(uint8_t sig, void *handler) { return 0; } +VALUE rack_call_rpc_handler(VALUE args) { + VALUE rpc_args = rb_ary_entry(args, 1); + return rb_funcall2(rb_ary_entry(args, 0), rb_intern("call"), RARRAY_LEN(rpc_args), RARRAY_PTR(rpc_args)); +} + +uint16_t uwsgi_ruby_rpc(void *func, uint8_t argc, char **argv, char *buffer) { + + uint8_t i; + VALUE rb_args = rb_ary_new2(2); + VALUE rb_rpc_args = rb_ary_new2(argc); + VALUE ret; + int error = 0; + char *rv; + size_t rl; + + rb_ary_store(rb_args, 0, (VALUE) func); + + for (i = 0; i < argc; i++) { + rb_ary_store(rb_rpc_args, i, rb_str_new2(argv[i])); + } + rb_ary_store(rb_args, 1, rb_rpc_args); + + + ret = rb_protect(rack_call_rpc_handler, rb_args, &error); + + if (error) { + uwsgi_ruby_exception(); + return 0; + } + + if (TYPE(ret) == T_STRING) { + rv = RSTRING_PTR(ret); + rl = RSTRING_LEN(ret); + if (rl <= 0xffff) { + memcpy(buffer, rv, rl); + return rl; + } + } + + return 0; + +} + + VALUE rack_uwsgi_add_cron(VALUE *class, VALUE rbsignum, VALUE rbmin, VALUE rbhour, VALUE rbday, VALUE rbmon, VALUE rbweek) { uint8_t uwsgi_signal = NUM2INT(rbsignum); @@ -421,7 +488,9 @@ int uwsgi_rack_init(){ ruby_script("uwsgi"); ur.signals_protector = rb_ary_new(); + ur.rpc_protector = rb_ary_new(); rb_gc_register_address(&ur.signals_protector); + rb_gc_register_address(&ur.rpc_protector); VALUE rb_uwsgi_embedded = rb_define_module("UWSGI"); rb_define_module_function(rb_uwsgi_embedded, "suspend", uwsgi_ruby_suspend, 0); @@ -432,6 +501,7 @@ int uwsgi_rack_init(){ rb_define_module_function(rb_uwsgi_embedded, "async_connect", uwsgi_ruby_async_connect, 1); rb_define_module_function(rb_uwsgi_embedded, "signal", uwsgi_ruby_signal, 1); rb_define_module_function(rb_uwsgi_embedded, "register_signal", uwsgi_ruby_register_signal, 3); + rb_define_module_function(rb_uwsgi_embedded, "register_rpc", uwsgi_ruby_register_rpc, -1); rb_define_module_function(rb_uwsgi_embedded, "signal_registered", uwsgi_ruby_signal_registered, 1); rb_define_module_function(rb_uwsgi_embedded, "signal_wait", uwsgi_ruby_signal_wait, -1); rb_define_module_function(rb_uwsgi_embedded, "signal_received", uwsgi_ruby_signal_received, 0); @@ -1104,6 +1174,7 @@ struct uwsgi_plugin rack_plugin = { .magic = uwsgi_rack_magic, .mule = uwsgi_rack_mule, + .rpc = uwsgi_ruby_rpc, .suspend = uwsgi_rack_suspend, .resume = uwsgi_rack_resume, diff --git a/plugins/rack/uwsgi_rack.h b/plugins/rack/uwsgi_rack.h index 620c7299..98e99cd2 100644 --- a/plugins/rack/uwsgi_rack.h +++ b/plugins/rack/uwsgi_rack.h @@ -56,6 +56,7 @@ struct uwsgi_rack { // why why why !!!!????!!!??? VALUE signals_protector; + VALUE rpc_protector; VALUE dispatcher; VALUE rb_uwsgi_io_class; diff --git a/protocol.c b/protocol.c index a68dd656..5cc876f6 100644 --- a/protocol.c +++ b/protocol.c @@ -403,7 +403,9 @@ int uwsgi_parse_array(char *buffer, uint16_t size, char **argv, uint8_t *argc) { if (ptrbuf + strsize <= bufferend) { // item argv[*argc] = uwsgi_cheap_string(ptrbuf, strsize); +#ifdef UWSGI_DEBUG uwsgi_log("arg %s\n", argv[*argc]); +#endif ptrbuf += strsize; *argc = *argc + 1; } diff --git a/uwsgidsl.rb b/uwsgidsl.rb index c5648930..e8605237 100644 --- a/uwsgidsl.rb +++ b/uwsgidsl.rb @@ -52,3 +52,11 @@ end def postfork(&block) $postfork_chain << block end + +def rpc(name, &block) + if block.arity <= 0 + UWSGI.register_rpc(name, block, 0) + else + UWSGI.register_rpc(name, block, block.arity) + end +end