Skip to content

Commit

Permalink
WIP: fix zombie thread issue
Browse files Browse the repository at this point in the history
  • Loading branch information
ko1 committed Oct 11, 2023
1 parent b00c45d commit d8958c9
Show file tree
Hide file tree
Showing 6 changed files with 55 additions and 5 deletions.
4 changes: 4 additions & 0 deletions ractor.c
Original file line number Diff line number Diff line change
Expand Up @@ -2273,13 +2273,17 @@ ractor_check_blocking(rb_ractor_t *cr, unsigned int remained_thread_cnt, const c
}
}

void rb_threadptr_remove(rb_thread_t *th);

void
rb_ractor_living_threads_remove(rb_ractor_t *cr, rb_thread_t *th)
{
VM_ASSERT(cr == GET_RACTOR());
RUBY_DEBUG_LOG("r->threads.cnt:%d--", cr->threads.cnt);
ractor_check_blocking(cr, cr->threads.cnt - 1, __FILE__, __LINE__);

rb_threadptr_remove(th);

if (cr->threads.cnt == 1) {
vm_remove_ractor(th->vm, cr);
}
Expand Down
25 changes: 25 additions & 0 deletions thread_pthread.c
Original file line number Diff line number Diff line change
Expand Up @@ -2236,9 +2236,32 @@ static int native_thread_create_shared(rb_thread_t *th);
static void nt_free_stack(void *mstack);
#endif

void
rb_threadptr_remove(rb_thread_t *th)
{
#if USE_MN_THREADS
if (th->sched.malloc_stack) {
// dedicated
return;
}
else {
rb_vm_t *vm = th->vm;
th->sched.finished = false;

RB_VM_LOCK_ENTER();
{
ccan_list_add(&vm->ractor.sched.zombie_threads, &th->sched.node.zombie_threads);
}
RB_VM_LOCK_LEAVE();
}
#endif
}

void
rb_threadptr_sched_free(rb_thread_t *th)
{
fprintf(stderr, "rb_threadptr_sched_free th:%p\n", th);

#if USE_MN_THREADS
if (th->sched.malloc_stack) {
ruby_xfree(th->sched.context_stack);
Expand All @@ -2255,6 +2278,8 @@ rb_threadptr_sched_free(rb_thread_t *th)
ruby_xfree(th->sched.context);
VM_ASSERT((th->sched.context = NULL) == NULL);
}

th->nt = NULL;
#else
ruby_xfree(th->sched.context_stack);

Expand Down
4 changes: 4 additions & 0 deletions thread_pthread.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ struct rb_thread_sched_item {
// connected to vm->ractor.sched.running_threads
// locked by vm->ractor.sched.lock
struct ccan_list_node running_threads;

// connected to vm->ractor.sched.zombie_threads
struct ccan_list_node zombie_threads;
} node;

// this data should be protected by timer_th.waiting_lock
Expand Down Expand Up @@ -60,6 +63,7 @@ struct rb_thread_sched_item {
struct ccan_list_node node;
} waiting_reason;

bool finished;
bool malloc_stack;
void *context_stack;
struct coroutine_context *context;
Expand Down
12 changes: 7 additions & 5 deletions thread_pthread_mn.c
Original file line number Diff line number Diff line change
Expand Up @@ -420,17 +420,19 @@ co_start(struct coroutine_context *from, struct coroutine_context *self)
bool has_ready_ractor = vm->ractor.sched.grq_cnt > 0; // at least this ractor is not queued

rb_thread_t *next_th = sched->running;
struct rb_native_thread *nt = th->nt;
native_thread_assign(NULL, th);
rb_ractor_set_current_ec(th->ractor, NULL);

if (!has_ready_ractor && next_th && !next_th->nt) {
// switch to the next thread
thread_sched_set_lock_owner(sched, NULL);
rb_ractor_set_current_ec(th->ractor, NULL);
thread_sched_switch(th, next_th);
thread_sched_switch0(th->sched.context, next_th, nt);
th->sched.finished = true;
}
else {
struct rb_native_thread *nt = th->nt;
// switch to the next Ractor
rb_ractor_set_current_ec(th->ractor, NULL);
native_thread_assign(NULL, th);
th->sched.finished = true;
coroutine_transfer(self, nt->nt_context);
}
rb_bug("unreachable");
Expand Down
12 changes: 12 additions & 0 deletions vm.c
Original file line number Diff line number Diff line change
Expand Up @@ -2884,6 +2884,18 @@ rb_vm_mark(void *ptr)
}
}

if (!ccan_list_empty(&vm->ractor.sched.zombie_threads)) {
rb_thread_t *zombie_th, *next_zombie_th;
ccan_list_for_each_safe(&vm->ractor.sched.zombie_threads, zombie_th, next_zombie_th, sched.node.zombie_threads) {
if (zombie_th->sched.finished) {
ccan_list_del_init(&zombie_th->sched.node.zombie_threads);
}
else {
rb_gc_mark(zombie_th->self);
}
}
}

rb_rjit_mark();
}

Expand Down
3 changes: 3 additions & 0 deletions vm_core.h
Original file line number Diff line number Diff line change
Expand Up @@ -667,6 +667,8 @@ typedef struct rb_vm_struct {
// threads which switch context by timeslice
struct ccan_list_head timeslice_threads;

struct ccan_list_head zombie_threads;

// true if timeslice timer is not enable
bool timeslice_wait_inf;

Expand Down Expand Up @@ -1773,6 +1775,7 @@ rb_vm_living_threads_init(rb_vm_t *vm)
ccan_list_head_init(&vm->waiting_fds);
ccan_list_head_init(&vm->workqueue);
ccan_list_head_init(&vm->ractor.set);
ccan_list_head_init(&vm->ractor.sched.zombie_threads);
}

typedef int rb_backtrace_iter_func(void *, VALUE, int, VALUE);
Expand Down

0 comments on commit d8958c9

Please sign in to comment.