mirror of
https://github.com/ruby/ruby.git
synced 2025-08-15 13:39:04 +02:00
merge revision(s) 08b3a45bc9
: [Backport #21180]
Push a real iseq in rb_vm_push_frame_fname() Previously, vm_make_env_each() (used during proc creation and for the debug inspector C API) picked up the non-GC-allocated iseq that rb_vm_push_frame_fname() creates, which led to a SEGV when the GC tried to mark the non GC object. Put a real iseq imemo instead. Speed should be about the same since the old code also did a imemo allocation and a malloc allocation. Real iseq allows ironing out the special-casing of dummy frames in rb_execution_context_mark() and rb_execution_context_update(). A check is added to RubyVM::ISeq#eval, though, to stop attempts to run dummy iseqs. [Bug #21180] Co-authored-by: Aaron Patterson <tenderlove@ruby-lang.org>
This commit is contained in:
parent
d213eb7f45
commit
2b2ab1a67c
5 changed files with 46 additions and 25 deletions
19
iseq.c
19
iseq.c
|
@ -533,6 +533,19 @@ rb_iseq_pathobj_set(const rb_iseq_t *iseq, VALUE path, VALUE realpath)
|
|||
rb_iseq_pathobj_new(path, realpath));
|
||||
}
|
||||
|
||||
// Make a dummy iseq for a dummy frame that exposes a path for profilers to inspect
|
||||
rb_iseq_t *
|
||||
rb_iseq_alloc_with_dummy_path(VALUE fname)
|
||||
{
|
||||
rb_iseq_t *dummy_iseq = iseq_alloc();
|
||||
|
||||
ISEQ_BODY(dummy_iseq)->type = ISEQ_TYPE_TOP;
|
||||
RB_OBJ_WRITE(dummy_iseq, &ISEQ_BODY(dummy_iseq)->location.pathobj, fname);
|
||||
RB_OBJ_WRITE(dummy_iseq, &ISEQ_BODY(dummy_iseq)->location.label, fname);
|
||||
|
||||
return dummy_iseq;
|
||||
}
|
||||
|
||||
static rb_iseq_location_t *
|
||||
iseq_location_setup(rb_iseq_t *iseq, VALUE name, VALUE path, VALUE realpath, int first_lineno, const rb_code_location_t *code_location, const int node_id)
|
||||
{
|
||||
|
@ -1672,7 +1685,11 @@ rb_iseqw_to_iseq(VALUE iseqw)
|
|||
static VALUE
|
||||
iseqw_eval(VALUE self)
|
||||
{
|
||||
return rb_iseq_eval(iseqw_check(self));
|
||||
const rb_iseq_t *iseq = iseqw_check(self);
|
||||
if (0 == ISEQ_BODY(iseq)->iseq_size) {
|
||||
rb_raise(rb_eTypeError, "attempt to evaluate dummy InstructionSequence");
|
||||
}
|
||||
return rb_iseq_eval(iseq);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -139,6 +139,19 @@ class TestFiberScheduler < Test::Unit::TestCase
|
|||
end
|
||||
end
|
||||
|
||||
def test_iseq_compile_under_gc_stress_bug_21180
|
||||
Thread.new do
|
||||
scheduler = Scheduler.new
|
||||
Fiber.set_scheduler scheduler
|
||||
|
||||
Fiber.schedule do
|
||||
EnvUtil.under_gc_stress do
|
||||
RubyVM::InstructionSequence.compile_file(File::NULL)
|
||||
end
|
||||
end
|
||||
end.join
|
||||
end
|
||||
|
||||
def test_deadlock
|
||||
mutex = Thread::Mutex.new
|
||||
condition = Thread::ConditionVariable.new
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
# define RUBY_VERSION_MINOR RUBY_API_VERSION_MINOR
|
||||
#define RUBY_VERSION_TEENY 7
|
||||
#define RUBY_RELEASE_DATE RUBY_RELEASE_YEAR_STR"-"RUBY_RELEASE_MONTH_STR"-"RUBY_RELEASE_DAY_STR
|
||||
#define RUBY_PATCHLEVEL 133
|
||||
#define RUBY_PATCHLEVEL 134
|
||||
|
||||
#include "ruby/version.h"
|
||||
#include "ruby/internal/abi.h"
|
||||
|
|
24
vm.c
24
vm.c
|
@ -3327,21 +3327,19 @@ rb_execution_context_mark(const rb_execution_context_t *ec)
|
|||
const VALUE *ep = cfp->ep;
|
||||
VM_ASSERT(!!VM_ENV_FLAGS(ep, VM_ENV_FLAG_ESCAPED) == vm_ep_in_heap_p_(ec, ep));
|
||||
|
||||
if (VM_FRAME_TYPE(cfp) != VM_FRAME_MAGIC_DUMMY) {
|
||||
rb_gc_mark_movable(cfp->self);
|
||||
rb_gc_mark_movable((VALUE)cfp->iseq);
|
||||
rb_gc_mark_movable((VALUE)cfp->block_code);
|
||||
rb_gc_mark_movable(cfp->self);
|
||||
rb_gc_mark_movable((VALUE)cfp->iseq);
|
||||
rb_gc_mark_movable((VALUE)cfp->block_code);
|
||||
|
||||
if (!VM_ENV_LOCAL_P(ep)) {
|
||||
const VALUE *prev_ep = VM_ENV_PREV_EP(ep);
|
||||
if (VM_ENV_FLAGS(prev_ep, VM_ENV_FLAG_ESCAPED)) {
|
||||
rb_gc_mark_movable(prev_ep[VM_ENV_DATA_INDEX_ENV]);
|
||||
}
|
||||
if (!VM_ENV_LOCAL_P(ep)) {
|
||||
const VALUE *prev_ep = VM_ENV_PREV_EP(ep);
|
||||
if (VM_ENV_FLAGS(prev_ep, VM_ENV_FLAG_ESCAPED)) {
|
||||
rb_gc_mark_movable(prev_ep[VM_ENV_DATA_INDEX_ENV]);
|
||||
}
|
||||
|
||||
if (VM_ENV_FLAGS(ep, VM_ENV_FLAG_ESCAPED)) {
|
||||
rb_gc_mark_movable(ep[VM_ENV_DATA_INDEX_ENV]);
|
||||
rb_gc_mark(ep[VM_ENV_DATA_INDEX_ME_CREF]);
|
||||
}
|
||||
if (VM_ENV_FLAGS(ep, VM_ENV_FLAG_ESCAPED)) {
|
||||
rb_gc_mark_movable(ep[VM_ENV_DATA_INDEX_ENV]);
|
||||
rb_gc_mark(ep[VM_ENV_DATA_INDEX_ME_CREF]);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -444,15 +444,8 @@ rb_vm_pop_frame(rb_execution_context_t *ec)
|
|||
VALUE
|
||||
rb_vm_push_frame_fname(rb_execution_context_t *ec, VALUE fname)
|
||||
{
|
||||
VALUE tmpbuf = rb_imemo_tmpbuf_auto_free_pointer();
|
||||
void *ptr = ruby_xcalloc(sizeof(struct rb_iseq_constant_body) + sizeof(struct rb_iseq_struct), 1);
|
||||
rb_imemo_tmpbuf_set_ptr(tmpbuf, ptr);
|
||||
|
||||
struct rb_iseq_struct *dmy_iseq = (struct rb_iseq_struct *)ptr;
|
||||
struct rb_iseq_constant_body *dmy_body = (struct rb_iseq_constant_body *)&dmy_iseq[1];
|
||||
dmy_iseq->body = dmy_body;
|
||||
dmy_body->type = ISEQ_TYPE_TOP;
|
||||
dmy_body->location.pathobj = fname;
|
||||
rb_iseq_t *rb_iseq_alloc_with_dummy_path(VALUE fname);
|
||||
rb_iseq_t *dmy_iseq = rb_iseq_alloc_with_dummy_path(fname);
|
||||
|
||||
vm_push_frame(ec,
|
||||
dmy_iseq, //const rb_iseq_t *iseq,
|
||||
|
@ -465,7 +458,7 @@ rb_vm_push_frame_fname(rb_execution_context_t *ec, VALUE fname)
|
|||
0, // int local_size,
|
||||
0); // int stack_max
|
||||
|
||||
return tmpbuf;
|
||||
return (VALUE)dmy_iseq;
|
||||
}
|
||||
|
||||
/* method dispatch */
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue