diff --git a/core/exceptions.c b/core/exceptions.c index a1cf7efc..8777a073 100644 --- a/core/exceptions.c +++ b/core/exceptions.c @@ -81,9 +81,11 @@ static void append_backtrace_to_ubuf(uint16_t pos, char *value, uint16_t len, vo break; // text case 3: - if (uwsgi_buffer_append(ub, "text/code: \"", 12)) return; - if (uwsgi_buffer_append(ub, value, len)) return; - if (uwsgi_buffer_append(ub, "\" ", 2)) return; + if (len > 0) { + if (uwsgi_buffer_append(ub, "text/code: \"", 12)) return; + if (uwsgi_buffer_append(ub, value, len)) return; + if (uwsgi_buffer_append(ub, "\" ", 2)) return; + } break; // custom case 4: @@ -234,14 +236,16 @@ void uwsgi_manage_exception(struct wsgi_request *wsgi_req,int catch) { int do_exit = 0; - uwsgi.workers[uwsgi.mywid].cores[wsgi_req->async_id].exceptions++; - uwsgi_apps[wsgi_req->app_id].exceptions++; - if (uwsgi.reload_on_exception) { do_exit = 1; goto check_catch; } + if (!wsgi_req) goto log; + + uwsgi.workers[uwsgi.mywid].cores[wsgi_req->async_id].exceptions++; + uwsgi_apps[wsgi_req->app_id].exceptions++; + if (uwsgi.reload_on_exception_type && uwsgi.p[wsgi_req->uh->modifier1]->exception_class) { struct uwsgi_buffer *ub = uwsgi.p[wsgi_req->uh->modifier1]->exception_msg(wsgi_req); if (ub) { @@ -291,7 +295,7 @@ void uwsgi_manage_exception(struct wsgi_request *wsgi_req,int catch) { } check_catch: - if (catch) { + if (catch && wsgi_req) { if (uwsgi_exceptions_catch(wsgi_req)) { // for now, just goto, new features could be added goto log; diff --git a/plugins/rack/rack_plugin.c b/plugins/rack/rack_plugin.c index a792dcc6..9b9c36ab 100644 --- a/plugins/rack/rack_plugin.c +++ b/plugins/rack/rack_plugin.c @@ -41,21 +41,139 @@ struct uwsgi_option uwsgi_rack_options[] = { }; -void uwsgi_ruby_exception(void) { +static struct uwsgi_buffer *uwsgi_ruby_exception_class(struct wsgi_request *wsgi_req) { + VALUE err = rb_errinfo(); + VALUE e = rb_class_name(rb_class_of(err)); + struct uwsgi_buffer *ub = uwsgi_buffer_new(RSTRING_LEN(e)); + if (uwsgi_buffer_append(ub, RSTRING_PTR(e), RSTRING_LEN(e))) { + uwsgi_buffer_destroy(ub); + return NULL; + } + return ub; +} - VALUE lasterr = rb_gv_get("$!"); - VALUE message = rb_obj_as_string(lasterr); - uwsgi_log("%s\n", RSTRING_PTR(message)); - if(!NIL_P(rb_errinfo())) { - VALUE ary = rb_funcall(rb_errinfo(), rb_intern("backtrace"), 0); - int i; - for (i=0; ipos + 3 + ub_msg->pos); + if (uwsgi_buffer_append(ub, ub_msg->buf, ub_msg->pos)) goto error; + if (uwsgi_buffer_append(ub, " (", 2)) goto error; + if (uwsgi_buffer_append(ub, ub_class->buf, ub_class->pos)) goto error; + if (uwsgi_buffer_append(ub, ")", 1)) goto error; + + uwsgi_buffer_destroy(ub_class); + uwsgi_buffer_destroy(ub_msg); + + return ub; + + +error: + uwsgi_buffer_destroy(ub_class); + uwsgi_buffer_destroy(ub_msg); + uwsgi_buffer_destroy(ub); + return NULL; + +} + +// simulate ruby_error_print (this is sad... but it works well) +static void uwsgi_ruby_exception_log(struct wsgi_request *wsgi_req) { + VALUE err = rb_errinfo(); + VALUE eclass = rb_class_name(rb_class_of(err)); + VALUE msg = rb_funcall(err, rb_intern("message"), 0, 0); + + VALUE ary = rb_funcall(err, rb_intern("backtrace"), 0); + int i; + for (i=0; ivalue), &error ) ; if (error) { - uwsgi_ruby_exception(); + uwsgi_manage_exception(NULL, 0); } usl = usl->next; } @@ -399,7 +517,7 @@ void uwsgi_rack_init_apps(void) { error = 0; rb_protect( uwsgi_require_file, rb_str_new2(usl->value), &error ) ; if (error) { - uwsgi_ruby_exception(); + uwsgi_manage_exception(NULL, 0); } usl = usl->next; } @@ -407,7 +525,7 @@ void uwsgi_rack_init_apps(void) { if (ur.rack) { ur.dispatcher = rb_protect(init_rack_app, rb_str_new2(ur.rack), &error); if (error) { - uwsgi_ruby_exception(); + uwsgi_manage_exception(NULL, 0); exit(1); } if (ur.dispatcher == Qnil) { @@ -431,7 +549,7 @@ void uwsgi_rack_init_apps(void) { uwsgi_log("loading rails app %s\n", ur.rails); rb_protect( require_rails, 0, &error ) ; if (error) { - uwsgi_ruby_exception(); + uwsgi_manage_exception(NULL, 0); exit(1); } uwsgi_log("rails app %s ready\n", ur.rails); @@ -453,7 +571,7 @@ void uwsgi_rack_init_apps(void) { if (acim_call == Qtrue) { ur.dispatcher = rb_protect(uwsgi_rb_call_new, ac_dispatcher, &error); if (error) { - uwsgi_ruby_exception(); + uwsgi_manage_exception(NULL, 0); exit(1); } } @@ -463,7 +581,7 @@ void uwsgi_rack_init_apps(void) { uwsgi_log("non-rack rails version detected...loading thin adapter...\n"); rb_protect( require_thin, 0, &error ) ; if (error) { - uwsgi_ruby_exception(); + uwsgi_manage_exception(NULL, 0); exit(1); } VALUE thin_rack = rb_const_get(rb_cObject, rb_intern("Rack")); @@ -471,7 +589,7 @@ void uwsgi_rack_init_apps(void) { VALUE thin_rack_adapter_rails = rb_const_get(thin_rack_adapter, rb_intern("Rails")); ur.dispatcher = rb_protect( uwsgi_rb_call_new, thin_rack_adapter_rails, &error); if (error) { - uwsgi_ruby_exception(); + uwsgi_manage_exception(NULL, 0); exit(1); } } @@ -734,7 +852,7 @@ int uwsgi_rack_request(struct wsgi_request *wsgi_req) { else { ret = rb_protect( call_dispatch, env, &error); if (error) { - uwsgi_ruby_exception(); + uwsgi_manage_exception(wsgi_req, uwsgi.catch_exceptions); goto clear; } } @@ -757,7 +875,7 @@ int uwsgi_rack_request(struct wsgi_request *wsgi_req) { if (rb_respond_to( headers, rb_intern("each") )) { rb_protect( iterate_headers, headers, &error); if (error) { - uwsgi_ruby_exception(); + uwsgi_manage_exception(wsgi_req, uwsgi.catch_exceptions); goto clear; } } @@ -767,7 +885,7 @@ int uwsgi_rack_request(struct wsgi_request *wsgi_req) { if (rb_respond_to( body, rb_intern("to_path") )) { VALUE sendfile_path = rb_protect( body_to_path, body, &error); if (error) { - uwsgi_ruby_exception(); + uwsgi_manage_exception(wsgi_req, uwsgi.catch_exceptions); } else { int fd = open(RSTRING_PTR(sendfile_path), O_RDONLY); @@ -783,7 +901,7 @@ int uwsgi_rack_request(struct wsgi_request *wsgi_req) { else { rb_protect( iterate_body, body, &error); if (error) { - uwsgi_ruby_exception(); + uwsgi_manage_exception(wsgi_req, uwsgi.catch_exceptions); } } } @@ -792,7 +910,7 @@ int uwsgi_rack_request(struct wsgi_request *wsgi_req) { //uwsgi_log("calling close\n"); rb_protect( close_body, body, &error); if (error) { - uwsgi_ruby_exception(); + uwsgi_manage_exception(wsgi_req, uwsgi.catch_exceptions); } } @@ -843,7 +961,7 @@ VALUE init_rack_app( VALUE script ) { #endif rb_protect( require_rack, 0, &error ) ; if (error) { - uwsgi_ruby_exception(); + uwsgi_manage_exception(NULL, 0); return Qnil; } @@ -918,7 +1036,7 @@ int uwsgi_rack_mule(char *opt) { if (uwsgi_endswith(opt, (char *)".rb")) { rb_protect( uwsgi_require_file, rb_str_new2(opt), &error ) ; if (error) { - uwsgi_ruby_exception(); + uwsgi_manage_exception(NULL, 0); return 0; } return 1; @@ -943,7 +1061,7 @@ void uwsgi_rb_post_fork() { // call the post_fork_hook rb_protect(uwsgi_rb_pfh, 0, &error); if (error) { - uwsgi_ruby_exception(); + uwsgi_manage_exception(NULL, 0); } } @@ -961,7 +1079,7 @@ int uwsgi_rack_mule_msg(char *message, size_t len) { VALUE arg = rb_str_new(message, len); rb_protect(uwsgi_rb_mmh, arg, &error); if (error) { - uwsgi_ruby_exception(); + uwsgi_manage_exception(NULL, 0); } return 1; } @@ -987,7 +1105,7 @@ int uwsgi_rack_signal_handler(uint8_t sig, void *handler) { rb_ary_store(args, 1, rbsig); rb_protect(rack_call_signal_handler, args, &error); if (error) { - uwsgi_ruby_exception(); + uwsgi_manage_exception(NULL, 0); rb_gc(); return -1; } @@ -1035,7 +1153,7 @@ int uwsgi_rack_spooler(char *filename, char *buf, uint16_t len, char *body, size VALUE ret = rb_protect(uwsgi_rb_do_spooler, spool_dict, &error); if (error) { - uwsgi_ruby_exception(); + uwsgi_manage_exception(NULL, 0); rb_gc(); return -1; } @@ -1101,5 +1219,11 @@ struct uwsgi_plugin rack_plugin = { .suspend = uwsgi_rack_suspend, .resume = uwsgi_rack_resume, + + .exception_class = uwsgi_ruby_exception_class, + .exception_msg = uwsgi_ruby_exception_msg, + .exception_repr = uwsgi_ruby_exception_repr, + .exception_log = uwsgi_ruby_exception_log, + .backtrace = uwsgi_ruby_backtrace, }; diff --git a/plugins/rack/uwsgi_rack.h b/plugins/rack/uwsgi_rack.h index e8fbcb69..8aa0a30b 100644 --- a/plugins/rack/uwsgi_rack.h +++ b/plugins/rack/uwsgi_rack.h @@ -60,5 +60,4 @@ struct uwsgi_rack { }; -void uwsgi_ruby_exception(void); void uwsgi_rack_init_api(void);