зеркало из https://github.com/github/ruby.git
Fix Fiber with Thread issue on Windows [Bug #14642]
* cont.c (rb_threadptr_root_fiber_setup): divide into two functions: * rb_threadptr_root_fiber_setup_by_parent(): called by the parent thread. * rb_threadptr_root_fiber_setup_by_child(): called by the created thread. `rb_threadptr_root_fiber_setup()` is called by the parent thread and set fib->fib_handle by ConvertThreadToFiber() on the parent thread on Windows enveironment. This means that root_fib->fib_handle of child thread is initialized with parent thread's Fiber handle. Furthermore, second call of `ConvertThreadToFiber()` for the same thread fails. This patch solves this weird situateion. However, maybe we can make more clean code. * thread.c (thread_start_func_2): call `rb_threadptr_root_fiber_setup_by_child()` at thread initialize routine. * vm.c (th_init): call `rb_threadptr_root_fiber_setup_by_parent()`. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@63073 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
Родитель
c3da162596
Коммит
db3cc675f3
28
cont.c
28
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
|
||||
|
|
|
@ -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
|
||||
|
|
2
thread.c
2
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
|
||||
|
|
4
vm.c
4
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
|
||||
|
|
Загрузка…
Ссылка в новой задаче