From e45c9a40a2ee2ca241565f5953af116cd2b5ab29 Mon Sep 17 00:00:00 2001 From: k0kubun Date: Sun, 14 Apr 2019 12:40:44 +0000 Subject: Do not execute MJIT copy job when ISeq is GC-ed I assumed that ISeq is never GC-ed by `in_jit` + `mjit_mark` on copy job ISeq, but unfortunately I found SEGV on `mjit_copy_job_handler` in which iseq->body was somehow Qnil. And it seems to be fixed by disabling the job when `mjit_free_iseq` is called for the ISeq. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67551 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- mjit.c | 10 +++++++++- mjit_worker.c | 6 ++++-- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/mjit.c b/mjit.c index 9d849b1411..bd5dd46b19 100644 --- a/mjit.c +++ b/mjit.c @@ -33,11 +33,16 @@ mjit_copy_job_handler(void *data) // Make sure that this job is never executed when: // 1. job is being modified // 2. alloca memory inside job is expired - // Note that job->iseq is guarded from GC by `mjit_mark`. + // 3. ISeq is GC-ed if (job->finish_p) { CRITICAL_SECTION_FINISH(3, "in mjit_copy_job_handler"); return; } + else if (job->iseq == NULL) { // ISeq GC notified in mjit_mark_iseq + job->finish_p = true; + CRITICAL_SECTION_FINISH(3, "in mjit_copy_job_handler"); + return; + } const struct rb_iseq_constant_body *body = job->iseq->body; if (job->cc_entries) { @@ -113,6 +118,9 @@ mjit_free_iseq(const rb_iseq_t *iseq) if (!mjit_enabled) return; CRITICAL_SECTION_START(4, "mjit_free_iseq"); + if (mjit_copy_job.iseq == iseq) { + mjit_copy_job.iseq = NULL; + } if (iseq->body->jit_unit) { // jit_unit is not freed here because it may be referred by multiple // lists of units. `get_from_list` and `mjit_finish` do the job. diff --git a/mjit_worker.c b/mjit_worker.c index be0910b611..e7f17ac2d3 100644 --- a/mjit_worker.c +++ b/mjit_worker.c @@ -1195,15 +1195,17 @@ mjit_copy_cache_from_main_thread(const rb_iseq_t *iseq, struct rb_call_cache *cc } CRITICAL_SECTION_START(3, "in mjit_copy_cache_from_main_thread"); - bool result = job->finish_p; + bool success_p = job->finish_p; // Disable dispatching this job in mjit_copy_job_handler while memory allocated by alloca // could be expired after finishing this function. job->finish_p = true; in_jit = true; // Prohibit GC during JIT compilation + if (job->iseq == NULL) // ISeq GC is notified in mjit_mark_iseq + success_p = false; job->iseq = NULL; // Allow future GC of this ISeq from here CRITICAL_SECTION_FINISH(3, "in mjit_copy_cache_from_main_thread"); - return result; + return success_p; } // The function implementing a worker. It is executed in a separate -- cgit v1.2.3