mirror of
https://github.com/clearlinux/uwsgi.git
synced 2026-09-05 21:21:53 +00:00
porte the ruby/rack plugin to the new exception api
This commit is contained in:
+11
-7
@@ -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;
|
||||
|
||||
+153
-29
@@ -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; i<RARRAY_LEN(ary); i++) {
|
||||
uwsgi_log("%s\n", RSTRING_PTR(RARRAY_PTR(ary)[i]));
|
||||
}
|
||||
static struct uwsgi_buffer *uwsgi_ruby_exception_msg(struct wsgi_request *wsgi_req) {
|
||||
VALUE err = rb_errinfo();
|
||||
VALUE e = rb_funcall(err, rb_intern("message"), 0, 0);
|
||||
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;
|
||||
}
|
||||
|
||||
static struct uwsgi_buffer *uwsgi_ruby_exception_repr(struct wsgi_request *wsgi_req) {
|
||||
struct uwsgi_buffer *ub_class = uwsgi_ruby_exception_class(wsgi_req);
|
||||
if (!ub_class) return NULL;
|
||||
|
||||
struct uwsgi_buffer *ub_msg = uwsgi_ruby_exception_msg(wsgi_req);
|
||||
if (!ub_msg) {
|
||||
uwsgi_buffer_destroy(ub_class);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct uwsgi_buffer *ub = uwsgi_buffer_new(ub_class->pos + 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; i<RARRAY_LEN(ary); i++) {
|
||||
if (i == 0) {
|
||||
uwsgi_log("%s: %s (%s)\n", RSTRING_PTR(RARRAY_PTR(ary)[i]), RSTRING_PTR(msg), RSTRING_PTR(eclass));
|
||||
}
|
||||
else {
|
||||
uwsgi_log("\tfrom %s\n", RSTRING_PTR(RARRAY_PTR(ary)[i]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static struct uwsgi_buffer *uwsgi_ruby_backtrace(struct wsgi_request *wsgi_req) {
|
||||
VALUE err = rb_errinfo();
|
||||
VALUE ary = rb_funcall(err, rb_intern("backtrace"), 0);
|
||||
int i;
|
||||
struct uwsgi_buffer *ub = uwsgi_buffer_new(4096);
|
||||
char *filename = NULL;
|
||||
char *function = NULL;
|
||||
for (i=0; i<RARRAY_LEN(ary); i++) {
|
||||
char *bt = RSTRING_PTR(RARRAY_PTR(ary)[i]);
|
||||
// ok let's start the C dance to parse the backtrace
|
||||
char *colon = strchr(bt, ':');
|
||||
if (!colon) continue;
|
||||
filename = uwsgi_concat2n(bt, colon-bt, "", 0);
|
||||
uint16_t filename_len = colon-bt;
|
||||
colon++; if (*colon == 0) goto error;
|
||||
char *lineno_ptr = colon;
|
||||
colon = strchr(lineno_ptr, ':');
|
||||
if (!colon) goto error;
|
||||
int64_t lineno = uwsgi_str_num(lineno_ptr, colon-lineno_ptr);
|
||||
colon++; if (*colon == 0) goto error;
|
||||
colon = strchr(lineno_ptr, '`');
|
||||
if (!colon) goto error;
|
||||
colon++; if (*colon == 0) goto error;
|
||||
char *function_ptr = colon;
|
||||
char *function_end = strchr(function_ptr, '\'');
|
||||
if (!function_end) goto error;
|
||||
function = uwsgi_concat2n(function_ptr, function_end-function_ptr, "", 0);
|
||||
uint16_t function_len = function_end-function_ptr;
|
||||
|
||||
if (uwsgi_buffer_u16le(ub, filename_len)) goto error;
|
||||
if (uwsgi_buffer_append(ub, filename, filename_len)) goto error;
|
||||
if (uwsgi_buffer_append_valnum(ub, lineno)) goto error;
|
||||
if (uwsgi_buffer_u16le(ub, function_len)) goto error;
|
||||
if (uwsgi_buffer_append(ub, function, function_len)) goto error;
|
||||
|
||||
// in ruby we do not have text/code nor custom
|
||||
if (uwsgi_buffer_u16le(ub, 0)) goto error;
|
||||
if (uwsgi_buffer_append(ub, "", 0)) goto error;
|
||||
if (uwsgi_buffer_u16le(ub, 0)) goto error;
|
||||
if (uwsgi_buffer_append(ub, "", 0)) goto error;
|
||||
|
||||
free(filename);
|
||||
filename = NULL;
|
||||
free(function);
|
||||
function = NULL;
|
||||
}
|
||||
|
||||
return ub;
|
||||
|
||||
error:
|
||||
uwsgi_buffer_destroy(ub);
|
||||
|
||||
if (filename) {
|
||||
free(filename);
|
||||
}
|
||||
|
||||
if (function) {
|
||||
free(function);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
VALUE rb_uwsgi_io_new(VALUE class, VALUE wr) {
|
||||
|
||||
@@ -200,7 +318,7 @@ uint16_t uwsgi_ruby_rpc(void *func, uint8_t argc, char **argv, uint16_t argvs[],
|
||||
ret = rb_protect(rack_call_rpc_handler, rb_args, &error);
|
||||
|
||||
if (error) {
|
||||
uwsgi_ruby_exception();
|
||||
uwsgi_manage_exception(NULL, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -369,7 +487,7 @@ void uwsgi_rack_preinit_apps() {
|
||||
int 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;
|
||||
}
|
||||
@@ -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,
|
||||
};
|
||||
|
||||
|
||||
@@ -60,5 +60,4 @@ struct uwsgi_rack {
|
||||
|
||||
};
|
||||
|
||||
void uwsgi_ruby_exception(void);
|
||||
void uwsgi_rack_init_api(void);
|
||||
|
||||
Reference in New Issue
Block a user