Revision: 4185 http://trac.macosforge.org/projects/ruby/changeset/4185 Author: martinlagardette@apple.com Date: 2010-06-01 19:01:31 -0700 (Tue, 01 Jun 2010) Log Message: ----------- Fix Obj-C exceptions thrown during a rescue context - Fixes #627 Modified Paths: -------------- MacRuby/trunk/dispatcher.cpp MacRuby/trunk/objc.h MacRuby/trunk/objc.m Modified: MacRuby/trunk/dispatcher.cpp =================================================================== --- MacRuby/trunk/dispatcher.cpp 2010-06-02 01:47:03 UTC (rev 4184) +++ MacRuby/trunk/dispatcher.cpp 2010-06-02 02:01:31 UTC (rev 4185) @@ -444,15 +444,18 @@ return (*stub)(imp, rcv, sel, argc, argv); } @catch (id exc) { - VALUE rbexc = rb_oc2rb_exception(exc); + bool created = false; + VALUE rbexc = rb_oc2rb_exception(exc, &created); #if __LP64__ if (rb_vm_current_exception() == Qnil) { - rb_vm_set_current_exception(rbexc); + rb_vm_set_current_exception(rbexc); + throw; } +#endif + if (created) { + rb_exc_raise(rbexc); + } throw; -#else - rb_exc_raise(rbexc); -#endif } abort(); // never reached } @@ -711,6 +714,7 @@ } std::string types; vm_gen_bs_func_types(argc, argv, bs_func, types); + printf("dispatching `%s' with types `%s'\n", (char *)selname, types.c_str()); cache->flag = MCACHE_FCALL; cache->sel = sel; Modified: MacRuby/trunk/objc.h =================================================================== --- MacRuby/trunk/objc.h 2010-06-02 01:47:03 UTC (rev 4184) +++ MacRuby/trunk/objc.h 2010-06-02 02:01:31 UTC (rev 4185) @@ -56,7 +56,7 @@ size_t name_len); id rb_rb2oc_exception(VALUE exc); -VALUE rb_oc2rb_exception(id exc); +VALUE rb_oc2rb_exception(id exc, bool *created); size_t rb_objc_type_size(const char *type); Modified: MacRuby/trunk/objc.m =================================================================== --- MacRuby/trunk/objc.m 2010-06-02 01:47:03 UTC (rev 4184) +++ MacRuby/trunk/objc.m 2010-06-02 02:01:31 UTC (rev 4185) @@ -621,26 +621,32 @@ { NSString *name = [NSString stringWithUTF8String:rb_obj_classname(exc)]; NSString *reason = (NSString *)rb_format_exception_message(exc); -#if 0 - // This is technically not required, and it seems that some exceptions - // don't like to be treated like NSDictionary values... NSDictionary *dict = [NSDictionary dictionaryWithObject:(id)exc forKey:@"RubyException"]; -#else - NSDictionary *dict = nil; -#endif return [NSException exceptionWithName:name reason:reason userInfo:dict]; } VALUE -rb_oc2rb_exception(id exc) +rb_oc2rb_exception(id exc, bool *created) { - char buf[1000]; - snprintf(buf, sizeof buf, "%s: %s", [[exc name] UTF8String], - [[exc reason] UTF8String]); - VALUE e = rb_exc_new2(rb_eRuntimeError, buf); - // Set the backtrace for Obj-C exceptions - rb_iv_set(e, "bt", rb_vm_backtrace(0)); + VALUE e; + id rubyExc; + + rubyExc = [[exc userInfo] objectForKey:@"RubyException"]; + if (rubyExc == nil) { + *created = true; + + char buf[1000]; + snprintf(buf, sizeof buf, "%s: %s", [[exc name] UTF8String], + [[exc reason] UTF8String]); + e = rb_exc_new2(rb_eRuntimeError, buf); + // Set the backtrace for Obj-C exceptions + rb_iv_set(e, "bt", rb_vm_backtrace(0)); + } + else { + *created = false; + e = (VALUE)rubyExc; + } return e; }