Revision
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

Diff

Modified: MacRuby/trunk/bin/rubyc (4536 => 4537)


--- 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 (4536 => 4537)


--- 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;
     }