diff --git a/ChangeLog b/ChangeLog index f01f96f074..17a01898d9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +Sat Oct 10 14:09:40 2009 Marc-Andre Lafortune + + * thread.c (rb_threadptr_execute_interrupts_rec, rb_threadptr_raise): + Thread#raise with no argument will now re-raise the current exception + if there is one [ruby-core:25367] + + * eval.c (get_errinfo, rb_rubylevel_thread_errinfo): Getter for + current exception for a given thread + Sat Oct 10 12:21:31 2009 Nobuyoshi Nakada * transcode.c (rb_transcoding, str_transcoding_resize): fixed diff --git a/eval.c b/eval.c index bf5b5c8f87..e9e76ad4fb 100644 --- a/eval.c +++ b/eval.c @@ -902,9 +902,8 @@ VALUE rb_f_trace_var(); VALUE rb_f_untrace_var(); static VALUE * -errinfo_place(void) +errinfo_place(rb_thread_t *th) { - rb_thread_t *th = GET_THREAD(); rb_control_frame_t *cfp = th->cfp; rb_control_frame_t *end_cfp = RUBY_VM_END_CONTROL_FRAME(th); @@ -925,18 +924,23 @@ errinfo_place(void) } static VALUE -get_errinfo(void) +get_thread_errinfo(rb_thread_t *th) { - VALUE *ptr = errinfo_place(); + VALUE *ptr = errinfo_place(th); if (ptr) { return *ptr; } else { - rb_thread_t *th = GET_THREAD(); return th->errinfo; } } +static VALUE +get_errinfo(void) +{ + return get_thread_errinfo(GET_THREAD()); +} + static VALUE errinfo_getter(ID id) { @@ -951,7 +955,7 @@ errinfo_setter(VALUE val, ID id, VALUE *var) rb_raise(rb_eTypeError, "assigning non-exception to $!"); } else { - VALUE *ptr = errinfo_place(); + VALUE *ptr = errinfo_place(GET_THREAD()); if (ptr) { *ptr = val; } @@ -984,6 +988,12 @@ rb_rubylevel_errinfo(void) return get_errinfo(); } +VALUE +rb_rubylevel_thread_errinfo(rb_thread_t *th) +{ + return get_thread_errinfo(th); +} + static VALUE errat_getter(ID id) { diff --git a/eval_intern.h b/eval_intern.h index b7790828dc..c5b1fd8b2e 100644 --- a/eval_intern.h +++ b/eval_intern.h @@ -212,6 +212,7 @@ void rb_thread_terminate_all(void); VALUE rb_vm_top_self(); VALUE rb_vm_cbase(void); void rb_trap_restore_mask(void); +VALUE rb_rubylevel_thread_errinfo(rb_thread_t *); #ifndef CharNext /* defined as CharNext[AW] on Windows. */ #define CharNext(p) ((p) + mblen(p, RUBY_MBCHAR_MAXSIZE)) diff --git a/thread.c b/thread.c index da4cf9cf30..fc33fe568d 100644 --- a/thread.c +++ b/thread.c @@ -76,6 +76,7 @@ void rb_thread_stop_timer_thread(void); static const VALUE eKillSignal = INT2FIX(0); static const VALUE eTerminateSignal = INT2FIX(1); +static const VALUE eReRaiseSignal = INT2FIX(2); static volatile int system_working = 1; inline static void @@ -1246,6 +1247,10 @@ rb_threadptr_execute_interrupts_rec(rb_thread_t *th, int sched_depth) TH_JUMP_TAG(th, TAG_FATAL); } else { + if (err == eReRaiseSignal) { + err = rb_rubylevel_thread_errinfo(th); + err = rb_make_exception(NIL_P(err) ? 0 : 1, &err); + } rb_exc_raise(err); } } @@ -1312,7 +1317,12 @@ rb_threadptr_raise(rb_thread_t *th, int argc, VALUE *argv) goto again; } - exc = rb_make_exception(argc, argv); + if (argc == 0) { + exc = eReRaiseSignal; + } + else { + exc = rb_make_exception(argc, argv); + } th->thrown_errinfo = exc; rb_threadptr_ready(th); return Qnil;