aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cont.c28
-rw-r--r--test/ruby/test_fiber.rb9
-rw-r--r--thread.c2
-rw-r--r--vm.c4
4 files changed, 38 insertions, 5 deletions
diff --git a/cont.c b/cont.c
index 9cb0d96157..253a056f64 100644
--- a/cont.c
+++ b/cont.c
@@ -1464,6 +1464,18 @@ rb_fiber_start(void)
VM_UNREACHABLE(rb_fiber_start);
}
+#ifdef _WIN32
+static HANDLE
+win32_convert_thread_to_fiber(void)
+{
+ HANDLE fib_handle = ConvertThreadToFiber(0);
+ if (!fib_handle) {
+ rb_bug("rb_threadptr_root_fiber_setup_by_child: ConvertThreadToFiber() failed - %s\n", rb_w32_strerror(-1));
+ }
+ return fib_handle;
+}
+#endif
+
static rb_fiber_t *
root_fiber_alloc(rb_thread_t *th)
{
@@ -1480,7 +1492,7 @@ root_fiber_alloc(rb_thread_t *th)
#if FIBER_USE_NATIVE
#ifdef _WIN32
if (fib->fib_handle == 0) {
- fib->fib_handle = ConvertThreadToFiber(0);
+ fib->fib_handle = win32_convert_thread_to_fiber();
}
#endif
#endif
@@ -1488,7 +1500,7 @@ root_fiber_alloc(rb_thread_t *th)
}
void
-rb_threadptr_root_fiber_setup(rb_thread_t *th)
+rb_threadptr_root_fiber_setup_by_parent(rb_thread_t *th)
{
rb_fiber_t *fib = ruby_mimmalloc(sizeof(rb_fiber_t));
MEMZERO(fib, rb_fiber_t, 1);
@@ -1497,10 +1509,20 @@ rb_threadptr_root_fiber_setup(rb_thread_t *th)
fib->cont.saved_ec.thread_ptr = th;
fiber_status_set(fib, FIBER_RESUMED); /* skip CREATED */
th->ec = &fib->cont.saved_ec;
+}
+
+void
+rb_threadptr_root_fiber_setup_by_child(rb_thread_t *th)
+{
#if FIBER_USE_NATIVE
#ifdef _WIN32
+ rb_fiber_t *fib = th->ec->fiber_ptr;
+
if (fib->fib_handle == 0) {
- fib->fib_handle = ConvertThreadToFiber(0);
+ fib->fib_handle = win32_convert_thread_to_fiber();
+ }
+ else {
+ rb_bug("rb_threadptr_root_fiber_setup_by_child: fib_handle is not NULL.");
}
#endif
#endif
diff --git a/test/ruby/test_fiber.rb b/test/ruby/test_fiber.rb
index 7b513a11fa..6cb76d98d8 100644
--- a/test/ruby/test_fiber.rb
+++ b/test/ruby/test_fiber.rb
@@ -378,4 +378,13 @@ class TestFiber < Test::Unit::TestCase
assert_match(/terminated/, f.to_s)
assert_match(/resumed/, Fiber.current.to_s)
end
+
+ def assert_create_fiber_in_new_thread
+ ret = Thread.new{
+ Thread.new{
+ Fiber.new{Fiber.yield :ok}.resume
+ }.join
+ }.join
+ assert_euqal :ok, ret, '[Bug #14642]'
+ end
end
diff --git a/thread.c b/thread.c
index 1caea4976c..1ad454614c 100644
--- a/thread.c
+++ b/thread.c
@@ -643,6 +643,7 @@ thread_do_start(rb_thread_t *th, VALUE args)
}
void rb_ec_clear_current_thread_trace_func(const rb_execution_context_t *ec);
+void rb_threadptr_root_fiber_setup_by_child(rb_thread_t *th);
static int
thread_start_func_2(rb_thread_t *th, VALUE *stack_start, VALUE *register_stack_start)
@@ -662,6 +663,7 @@ thread_start_func_2(rb_thread_t *th, VALUE *stack_start, VALUE *register_stack_s
rb_bug("thread_start_func_2 must not be used for main thread");
ruby_thread_set_native(th);
+ rb_threadptr_root_fiber_setup_by_child(th);
th->ec->machine.stack_start = stack_start;
#ifdef __ia64
diff --git a/vm.c b/vm.c
index 1a57f2c6d1..df80bb94d3 100644
--- a/vm.c
+++ b/vm.c
@@ -2425,7 +2425,7 @@ rb_execution_context_mark(const rb_execution_context_t *ec)
}
void rb_fiber_mark_self(rb_fiber_t *fib);
-void rb_threadptr_root_fiber_setup(rb_thread_t *th);
+void rb_threadptr_root_fiber_setup_by_parent(rb_thread_t *th);
void rb_threadptr_root_fiber_release(rb_thread_t *th);
static void
@@ -2533,7 +2533,7 @@ static void
th_init(rb_thread_t *th, VALUE self)
{
th->self = self;
- rb_threadptr_root_fiber_setup(th);
+ rb_threadptr_root_fiber_setup_by_parent(th);
/* allocate thread stack */
#ifdef USE_SIGALTSTACK