add indirection on thread start to avoid ObjC exception issues
In Mac OS X 10.11, something about the use of exceptions triggers a libunwind stack traversal, and that traversal runs into trouble with Racket's stack mangling for threads. Inserting generated code in the stack frame sequence causes libunwind to give up and avoids a crash (e.g., with `-j -l drracket` on startup).
This commit is contained in:
parent
f86c5dfe0a
commit
4d3852ae69
|
@ -348,6 +348,7 @@ struct scheme_jit_common_record {
|
||||||
void *list_ref_code, *list_tail_code;
|
void *list_ref_code, *list_tail_code;
|
||||||
void *finish_tail_call_code, *finish_tail_call_fixup_code;
|
void *finish_tail_call_code, *finish_tail_call_fixup_code;
|
||||||
void *module_run_start_code, *module_exprun_start_code, *module_start_start_code;
|
void *module_run_start_code, *module_exprun_start_code, *module_start_start_code;
|
||||||
|
void *thread_start_child_code;
|
||||||
void *box_flonum_from_stack_code, *box_flonum_from_reg_code;
|
void *box_flonum_from_stack_code, *box_flonum_from_reg_code;
|
||||||
void *fl1_fail_code[JIT_NUM_FL_KINDS], *fl2rr_fail_code[2][JIT_NUM_FL_KINDS];
|
void *fl1_fail_code[JIT_NUM_FL_KINDS], *fl2rr_fail_code[2][JIT_NUM_FL_KINDS];
|
||||||
void *fl2fr_fail_code[2][JIT_NUM_FL_KINDS], *fl2rf_fail_code[2][JIT_NUM_FL_KINDS];
|
void *fl2fr_fail_code[2][JIT_NUM_FL_KINDS], *fl2rf_fail_code[2][JIT_NUM_FL_KINDS];
|
||||||
|
|
|
@ -3639,6 +3639,33 @@ static int more_common0(mz_jit_state *jitter, void *_data)
|
||||||
scheme_jit_register_sub_func(jitter, sjc.module_start_start_code, scheme_eof);
|
scheme_jit_register_sub_func(jitter, sjc.module_start_start_code, scheme_eof);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* *** thread_start_child_code *** */
|
||||||
|
/* A simple indirection to generate code that libunwind can't follow,
|
||||||
|
particularly as used by exceptions in the Objective-C runtime */
|
||||||
|
{
|
||||||
|
int in;
|
||||||
|
|
||||||
|
sjc.thread_start_child_code = jit_get_ip();
|
||||||
|
jit_prolog(2);
|
||||||
|
in = jit_arg_p();
|
||||||
|
jit_getarg_p(JIT_R0, in); /* child */
|
||||||
|
in = jit_arg_p();
|
||||||
|
jit_getarg_p(JIT_R1, in); /* child_thunk */
|
||||||
|
CHECK_LIMIT();
|
||||||
|
mz_push_locals();
|
||||||
|
|
||||||
|
jit_prepare(2);
|
||||||
|
jit_pusharg_p(JIT_R1);
|
||||||
|
jit_pusharg_p(JIT_R0);
|
||||||
|
(void)mz_finish(scheme_do_thread_start_child);
|
||||||
|
CHECK_LIMIT();
|
||||||
|
mz_pop_locals();
|
||||||
|
jit_ret();
|
||||||
|
CHECK_LIMIT();
|
||||||
|
|
||||||
|
scheme_jit_register_sub_func(jitter, sjc.thread_start_child_code, scheme_eof);
|
||||||
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -689,6 +689,7 @@ void scheme_jit_now(Scheme_Object *f)
|
||||||
typedef void *(*Module_Run_Proc)(Scheme_Env *menv, Scheme_Env *env, Scheme_Object **name);
|
typedef void *(*Module_Run_Proc)(Scheme_Env *menv, Scheme_Env *env, Scheme_Object **name);
|
||||||
typedef void *(*Module_Exprun_Proc)(Scheme_Env *menv, int set_ns, Scheme_Object **name);
|
typedef void *(*Module_Exprun_Proc)(Scheme_Env *menv, int set_ns, Scheme_Object **name);
|
||||||
typedef void *(*Module_Start_Proc)(struct Start_Module_Args *a, Scheme_Object **name);
|
typedef void *(*Module_Start_Proc)(struct Start_Module_Args *a, Scheme_Object **name);
|
||||||
|
typedef void (*Thread_Start_Child_Proc)(Scheme_Thread *child, Scheme_Object *child_thunk);
|
||||||
|
|
||||||
void *scheme_module_run_start(Scheme_Env *menv, Scheme_Env *env, Scheme_Object *name)
|
void *scheme_module_run_start(Scheme_Env *menv, Scheme_Env *env, Scheme_Object *name)
|
||||||
{
|
{
|
||||||
|
@ -717,8 +718,23 @@ void *scheme_module_start_start(struct Start_Module_Args *a, Scheme_Object *name
|
||||||
return scheme_module_start_finish(a);
|
return scheme_module_start_finish(a);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void scheme_thread_start_child(Scheme_Thread *child, Scheme_Object *child_thunk)
|
||||||
|
{
|
||||||
|
Thread_Start_Child_Proc proc = (Thread_Start_Child_Proc)sjc.thread_start_child_code;
|
||||||
|
if (proc)
|
||||||
|
proc(child, child_thunk);
|
||||||
|
else
|
||||||
|
scheme_do_thread_start_child(child, child_thunk);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
void* scheme_jit_find_code_end(void *p) { return NULL; }
|
void* scheme_jit_find_code_end(void *p) { return NULL; }
|
||||||
|
|
||||||
|
void scheme_thread_start_child(Scheme_Thread *child, Scheme_Object *child_thunk)
|
||||||
|
{
|
||||||
|
return scheme_do_thread_start_child(child, child_thunk);
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -667,6 +667,9 @@ void scheme_suspend_remembered_threads(void);
|
||||||
void scheme_resume_remembered_threads(void);
|
void scheme_resume_remembered_threads(void);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
void scheme_thread_start_child(Scheme_Thread *child, Scheme_Object *child_thunk);
|
||||||
|
void scheme_do_thread_start_child(Scheme_Thread *child, Scheme_Object *child_thunk);
|
||||||
|
|
||||||
int scheme_wait_until_suspend_ok(void);
|
int scheme_wait_until_suspend_ok(void);
|
||||||
|
|
||||||
#ifdef MZ_USE_MZRT
|
#ifdef MZ_USE_MZRT
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
Racket
|
Racket
|
||||||
Copyright (c) 2004-2015 PLT Design Inc.
|
Copyright (c) 2004-2014 PLT Design Inc.
|
||||||
Copyright (c) 1995-2001 Matthew Flatt
|
Copyright (c) 1995-2001 Matthew Flatt
|
||||||
|
|
||||||
This library is free software; you can redistribute it and/or
|
This library is free software; you can redistribute it and/or
|
||||||
|
@ -3167,6 +3167,11 @@ static void start_child(Scheme_Thread * volatile child,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void scheme_do_thread_start_child(Scheme_Thread *child, Scheme_Object *child_eval)
|
||||||
|
{
|
||||||
|
return start_child(child, child_eval);
|
||||||
|
}
|
||||||
|
|
||||||
static Scheme_Object *make_subprocess(Scheme_Object *child_thunk,
|
static Scheme_Object *make_subprocess(Scheme_Object *child_thunk,
|
||||||
void *child_start,
|
void *child_start,
|
||||||
Scheme_Config *config,
|
Scheme_Config *config,
|
||||||
|
@ -3223,7 +3228,7 @@ static Scheme_Object *make_subprocess(Scheme_Object *child_thunk,
|
||||||
child->stack_start = child_start;
|
child->stack_start = child_start;
|
||||||
|
|
||||||
/* Sets the child's jmpbuf for swapping in later: */
|
/* Sets the child's jmpbuf for swapping in later: */
|
||||||
start_child(child, child_thunk);
|
scheme_thread_start_child(child, child_thunk);
|
||||||
|
|
||||||
if (scheme_notify_multithread && turn_on_multi) {
|
if (scheme_notify_multithread && turn_on_multi) {
|
||||||
scheme_notify_multithread(1);
|
scheme_notify_multithread(1);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user