Ensure vm_stack
is cleared after fork.
This commit is contained in:
parent
6bf1285b20
commit
dbc2b89bc0
12
cont.c
12
cont.c
@ -268,13 +268,6 @@ fiber_status_set(rb_fiber_t *fib, enum fiber_status s)
|
|||||||
fib->status = s;
|
fib->status = s;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
rb_ec_set_vm_stack(rb_execution_context_t *ec, VALUE *stack, size_t size)
|
|
||||||
{
|
|
||||||
ec->vm_stack = stack;
|
|
||||||
ec->vm_stack_size = size;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
ec_switch(rb_thread_t *th, rb_fiber_t *fib)
|
ec_switch(rb_thread_t *th, rb_fiber_t *fib)
|
||||||
{
|
{
|
||||||
@ -705,7 +698,7 @@ cont_capture(volatile int *volatile stat)
|
|||||||
cont->saved_vm_stack.ptr = ALLOC_N(VALUE, ec->vm_stack_size);
|
cont->saved_vm_stack.ptr = ALLOC_N(VALUE, ec->vm_stack_size);
|
||||||
MEMCPY(cont->saved_vm_stack.ptr, ec->vm_stack, VALUE, ec->vm_stack_size);
|
MEMCPY(cont->saved_vm_stack.ptr, ec->vm_stack, VALUE, ec->vm_stack_size);
|
||||||
#endif
|
#endif
|
||||||
rb_ec_set_vm_stack(&cont->saved_ec, NULL, 0);
|
rb_ec_clear_vm_stack(&cont->saved_ec);
|
||||||
cont_save_machine_stack(th, cont);
|
cont_save_machine_stack(th, cont);
|
||||||
|
|
||||||
/* backup ensure_list to array for search in another context */
|
/* backup ensure_list to array for search in another context */
|
||||||
@ -1793,8 +1786,7 @@ rb_fiber_close(rb_fiber_t *fib)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rb_ec_set_vm_stack(ec, NULL, 0);
|
rb_ec_clear_vm_stack(ec);
|
||||||
ec->cfp = NULL;
|
|
||||||
|
|
||||||
#if !FIBER_USE_NATIVE
|
#if !FIBER_USE_NATIVE
|
||||||
/* should not mark machine stack any more */
|
/* should not mark machine stack any more */
|
||||||
|
4
thread.c
4
thread.c
@ -596,7 +596,11 @@ thread_cleanup_func_before_exec(void *th_ptr)
|
|||||||
{
|
{
|
||||||
rb_thread_t *th = th_ptr;
|
rb_thread_t *th = th_ptr;
|
||||||
th->status = THREAD_KILLED;
|
th->status = THREAD_KILLED;
|
||||||
|
// The thread stack doesn't exist in the forked process:
|
||||||
th->ec->machine.stack_start = th->ec->machine.stack_end = NULL;
|
th->ec->machine.stack_start = th->ec->machine.stack_end = NULL;
|
||||||
|
|
||||||
|
// The vm_stack is `alloca`ed on the thread stack, so it's gone too:
|
||||||
|
rb_ec_clear_vm_stack(th->ec);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
36
vm.c
36
vm.c
@ -2514,7 +2514,7 @@ rb_execution_context_mark(const rb_execution_context_t *ec)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* mark VM stack */
|
/* mark VM stack */
|
||||||
if (ec->vm_stack && ec->cfp) {
|
if (ec->vm_stack) {
|
||||||
VALUE *p = ec->vm_stack;
|
VALUE *p = ec->vm_stack;
|
||||||
VALUE *sp = ec->cfp->sp;
|
VALUE *sp = ec->cfp->sp;
|
||||||
rb_control_frame_t *cfp = ec->cfp;
|
rb_control_frame_t *cfp = ec->cfp;
|
||||||
@ -2685,20 +2685,36 @@ thread_alloc(VALUE klass)
|
|||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline void
|
||||||
|
rb_ec_set_vm_stack(rb_execution_context_t *ec, VALUE *stack, size_t size)
|
||||||
|
{
|
||||||
|
ec->vm_stack = stack;
|
||||||
|
ec->vm_stack_size = size;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
rb_ec_initialize_vm_stack(rb_execution_context_t *ec, VALUE *stack, size_t size)
|
rb_ec_initialize_vm_stack(rb_execution_context_t *ec, VALUE *stack, size_t size)
|
||||||
{
|
{
|
||||||
rb_ec_set_vm_stack(ec, stack, size);
|
rb_ec_set_vm_stack(ec, stack, size);
|
||||||
|
|
||||||
ec->cfp = (void *)(ec->vm_stack + ec->vm_stack_size);
|
ec->cfp = (void *)(ec->vm_stack + ec->vm_stack_size);
|
||||||
|
|
||||||
rb_vm_push_frame(ec,
|
rb_vm_push_frame(ec,
|
||||||
NULL /* dummy iseq */,
|
NULL /* dummy iseq */,
|
||||||
VM_FRAME_MAGIC_DUMMY | VM_ENV_FLAG_LOCAL | VM_FRAME_FLAG_FINISH | VM_FRAME_FLAG_CFRAME /* dummy frame */,
|
VM_FRAME_MAGIC_DUMMY | VM_ENV_FLAG_LOCAL | VM_FRAME_FLAG_FINISH | VM_FRAME_FLAG_CFRAME /* dummy frame */,
|
||||||
Qnil /* dummy self */, VM_BLOCK_HANDLER_NONE /* dummy block ptr */,
|
Qnil /* dummy self */, VM_BLOCK_HANDLER_NONE /* dummy block ptr */,
|
||||||
0 /* dummy cref/me */,
|
0 /* dummy cref/me */,
|
||||||
0 /* dummy pc */, ec->vm_stack, 0, 0
|
0 /* dummy pc */, ec->vm_stack, 0, 0
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
rb_ec_clear_vm_stack(rb_execution_context_t *ec)
|
||||||
|
{
|
||||||
|
rb_ec_set_vm_stack(ec, NULL, 0);
|
||||||
|
|
||||||
|
// Avoid dangling pointers:
|
||||||
|
ec->cfp = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -907,6 +907,10 @@ void rb_ec_set_vm_stack(rb_execution_context_t *ec, VALUE *stack, size_t size);
|
|||||||
// @param size the size of the stack, as in `VALUE stack[size]`.
|
// @param size the size of the stack, as in `VALUE stack[size]`.
|
||||||
void rb_ec_initialize_vm_stack(rb_execution_context_t *ec, VALUE *stack, size_t size);
|
void rb_ec_initialize_vm_stack(rb_execution_context_t *ec, VALUE *stack, size_t size);
|
||||||
|
|
||||||
|
// Clear (set to `NULL`) the vm_stack pointer and frame pointer in the execution context.
|
||||||
|
// @param ec the execution context to update.
|
||||||
|
void rb_ec_clear_vm_stack(rb_execution_context_t *ec);
|
||||||
|
|
||||||
typedef struct rb_thread_struct {
|
typedef struct rb_thread_struct {
|
||||||
struct list_node vmlt_node;
|
struct list_node vmlt_node;
|
||||||
VALUE self;
|
VALUE self;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user