Revision: 4537 http://trac.macosforge.org/projects/ruby/changeset/4537 Author: lsansonetti@apple.com Date: 2010-09-24 01:32:18 -0700 (Fri, 24 Sep 2010) Log Message: ----------- fix a bug when exceptions raised inside .rbo entry point functions would not be properly propagated since the entry point was directly executed from the dylib constructor trampoline which isn't compiled with unwind tables; instead we now call the entry point right after dlopen() (which is exception safe) and use the constructor to register a pointer to it Modified Paths: -------------- MacRuby/trunk/bin/rubyc MacRuby/trunk/dln.c Modified: MacRuby/trunk/bin/rubyc =================================================================== --- MacRuby/trunk/bin/rubyc 2010-09-23 21:33:11 UTC (rev 4536) +++ MacRuby/trunk/bin/rubyc 2010-09-24 08:32:18 UTC (rev 4537) @@ -177,7 +177,7 @@ # Compile the assembly. tmp_obj = gen_tmpfile(base + arch, 'o') - execute("#{@gcc} -c -arch #{arch} \"#{asm}\" -o \"#{tmp_obj}\"") + execute("#{@gcc} -fexceptions -c -arch #{arch} \"#{asm}\" -o \"#{tmp_obj}\"") tmp_objs << tmp_obj end @@ -200,10 +200,10 @@ # Generate main file. main_txt = <<EOS extern "C" { + void rb_mrep_register(void *); void *#{init_func}(void *, void *); - void *rb_vm_top_self(void); __attribute__((constructor)) static void __init__(void) { - #{init_func}(rb_vm_top_self(), 0); + rb_mrep_register((void *)#{init_func}); } } EOS @@ -212,7 +212,7 @@ main = gen_tmpfile('main', 'c') File.open(main, 'w') { |io| io.write(main_txt) } linkf = @internal ? "-L. -lmacruby" : "-L#{RbConfig::CONFIG['libdir']} -lmacruby" - execute("#{@gcxx} \"#{main}\" -dynamic -bundle -undefined suppress -flat_namespace #{arch_flags} #{linkf} \"#{obj}\" -o \"#{output}\"") + execute("#{@gcxx} \"#{main}\" -fexceptions -dynamic -bundle -undefined suppress -flat_namespace #{arch_flags} #{linkf} \"#{obj}\" -o \"#{output}\"") strip(output) end Modified: MacRuby/trunk/dln.c =================================================================== --- MacRuby/trunk/dln.c 2010-09-23 21:33:11 UTC (rev 4536) +++ MacRuby/trunk/dln.c 2010-09-24 08:32:18 UTC (rev 4537) @@ -10,7 +10,10 @@ **********************************************************************/ #include "ruby/macruby.h" +#include "ruby/node.h" +#include "vm.h" #include "dln.h" + #include <stdlib.h> #include <alloca.h> #include <string.h> @@ -73,6 +76,17 @@ bool ruby_is_miniruby = false; +// This function is called back from .rbo files' gcc constructors, passing a +// pointer to their entry point function, during dlopen(). The entry point +// function is called right after dlopen() directly. This is because C++ +// exceptions raised within a gcc constructor are not properly propagated. +static void *__mrep__ = NULL; +void +rb_mrep_register(void *imp) +{ + __mrep__ = imp; +} + void* dln_load(const char *file, bool call_init) { @@ -92,6 +106,7 @@ void *handle; /* Load file */ + __mrep__ = NULL; if ((handle = (void*)dlopen(file, RTLD_LAZY|RTLD_GLOBAL)) == NULL) { error = dln_strerror(); goto failed; @@ -108,6 +123,10 @@ /* Call the init code */ (*init_fct)(); } + else { + assert(__mrep__ != NULL); + ((IMP)__mrep__)((id)rb_vm_top_self(), 0); + } return handle; }