summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog6
-rw-r--r--eval.c13
-rw-r--r--ext/-test-/exception/dataerror.c31
-rw-r--r--test/-ext-/exception/test_data_error.rb14
4 files changed, 58 insertions, 6 deletions
diff --git a/ChangeLog b/ChangeLog
index 6c5f723..198e661 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+Sat Nov 30 17:46:35 2013 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * eval.c (ruby_cleanup): determine exit status and signal to terminate
+ before finalization, to get rid of access destroyed T_DATA execption
+ object. [ruby-core:58643] [Bug #9167]
+
Sat Nov 30 16:25:14 2013 Nobuyoshi Nakada <nobu@ruby-lang.org>
* enumerator.c (enumerator_with_index): should not store local variable
diff --git a/eval.c b/eval.c
index 15b0db2..f3275ad 100644
--- a/eval.c
+++ b/eval.c
@@ -192,12 +192,6 @@ ruby_cleanup(volatile int ex)
}
th->errinfo = errs[1];
ex = error_handle(ex);
- ruby_finalize_1();
-
- /* unlock again if finalizer took mutexes. */
- rb_threadptr_unlock_all_locking_mutexes(GET_THREAD());
- POP_TAG();
- rb_thread_stop_timer_thread(1);
#if EXIT_SUCCESS != 0 || EXIT_FAILURE != 1
switch (ex) {
@@ -232,6 +226,13 @@ ruby_cleanup(volatile int ex)
ex = EXIT_FAILURE;
}
}
+
+ ruby_finalize_1();
+
+ /* unlock again if finalizer took mutexes. */
+ rb_threadptr_unlock_all_locking_mutexes(GET_THREAD());
+ POP_TAG();
+ rb_thread_stop_timer_thread(1);
ruby_vm_destruct(GET_VM());
if (state) ruby_default_signal(state);
diff --git a/ext/-test-/exception/dataerror.c b/ext/-test-/exception/dataerror.c
new file mode 100644
index 0000000..d8beba8
--- /dev/null
+++ b/ext/-test-/exception/dataerror.c
@@ -0,0 +1,31 @@
+#include <ruby/ruby.h>
+
+static void
+dataerror_mark(void *ptr)
+{
+ rb_gc_mark((VALUE)ptr);
+}
+
+static void
+dataerror_free(void *ptr)
+{
+}
+
+static const rb_data_type_t dataerror_type = {
+ "Bug #9167",
+ {dataerror_mark, dataerror_free},
+};
+
+static VALUE
+dataerror_alloc(VALUE klass)
+{
+ VALUE n = rb_str_new_cstr("[Bug #9167] error");
+ return TypedData_Wrap_Struct(klass, &dataerror_type, (void *)n);
+}
+
+void
+Init_dataerror(VALUE klass)
+{
+ VALUE rb_eDataErr = rb_define_class_under(klass, "DataError", rb_eStandardError);
+ rb_define_alloc_func(rb_eDataErr, dataerror_alloc);
+}
diff --git a/test/-ext-/exception/test_data_error.rb b/test/-ext-/exception/test_data_error.rb
new file mode 100644
index 0000000..140de5b
--- /dev/null
+++ b/test/-ext-/exception/test_data_error.rb
@@ -0,0 +1,14 @@
+require 'test/unit'
+require_relative '../../ruby/envutil'
+
+module Bug
+ class TestException < Test::Unit::TestCase
+ def test_cleanup_data_error
+ bug9167 = '[ruby-core:58643] [Bug #9167]'
+ assert_normal_exit(<<-'end;', bug9167) # do
+ require '-test-/exception'
+ raise Bug::Exception::DataError, "Error"
+ end;
+ end
+ end
+end