From 9ffe0a69d158dca004e33f6859421bb609f01ac5 Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Sun, 28 Mar 2010 11:37:28 -0400 Subject: [PATCH] vm: use sigaltstack to handle callstack overflow properly --- vm/os-genunix.cpp | 2 +- vm/os-genunix.hpp | 2 -- vm/os-macosx.hpp | 3 --- vm/os-macosx.mm | 8 +++----- vm/os-unix.cpp | 23 ++++++++++++++++------- vm/os-unix.hpp | 1 - vm/os-windows.cpp | 2 ++ vm/os-windows.hpp | 1 - vm/vm.cpp | 8 +++++++- vm/vm.hpp | 45 +++++++++++++++++++++++++-------------------- 10 files changed, 54 insertions(+), 41 deletions(-) diff --git a/vm/os-genunix.cpp b/vm/os-genunix.cpp index 301b68fb52..c7449e867b 100644 --- a/vm/os-genunix.cpp +++ b/vm/os-genunix.cpp @@ -9,7 +9,7 @@ void factor_vm::c_to_factor_toplevel(cell quot) c_to_factor(quot); } -void init_signals() +void factor_vm::init_signals() { unix_init_signals(); } diff --git a/vm/os-genunix.hpp b/vm/os-genunix.hpp index 1972a728e6..c6123eca56 100644 --- a/vm/os-genunix.hpp +++ b/vm/os-genunix.hpp @@ -4,8 +4,6 @@ namespace factor #define VM_C_API extern "C" #define NULL_DLL NULL -void c_to_factor_toplevel(cell quot); -void init_signals(); void early_init(); const char *vm_executable_path(); const char *default_image_path(); diff --git a/vm/os-macosx.hpp b/vm/os-macosx.hpp index 93f6574367..8428f56998 100644 --- a/vm/os-macosx.hpp +++ b/vm/os-macosx.hpp @@ -5,14 +5,11 @@ namespace factor #define FACTOR_OS_STRING "macosx" #define NULL_DLL "libfactor.dylib" -void init_signals(); void early_init(); const char *vm_executable_path(); const char *default_image_path(); -void c_to_factor_toplevel(cell quot); - #define UAP_STACK_POINTER(ucontext) (((ucontext_t *)ucontext)->uc_stack.ss_sp) #define UAP_STACK_POINTER_TYPE void* diff --git a/vm/os-macosx.mm b/vm/os-macosx.mm index 92694a4599..4a6a3cb2b4 100644 --- a/vm/os-macosx.mm +++ b/vm/os-macosx.mm @@ -70,7 +70,7 @@ const char *default_image_path(void) return [returnVal UTF8String]; } -void init_signals(void) +void factor_vm::init_signals(void) { unix_init_signals(); mach_initialize(); @@ -87,11 +87,9 @@ Protocol *objc_getProtocol(char *name) u64 nano_count() { - u64 t; + u64 t = mach_absolute_time(); mach_timebase_info_data_t info; - kern_return_t ret; - t = mach_absolute_time(); - ret = mach_timebase_info(&info); + kern_return_t ret = mach_timebase_info(&info); if(ret != 0) fatal_error("mach_timebase_info failed",ret); return t * (info.numer/info.denom); diff --git a/vm/os-unix.cpp b/vm/os-unix.cpp index 8aa100aa01..7e88cedb0e 100644 --- a/vm/os-unix.cpp +++ b/vm/os-unix.cpp @@ -13,7 +13,7 @@ THREADHANDLE start_thread(void *(*start_routine)(void *),void *args) fatal_error("pthread_attr_setdetachstate() failed",0); if (pthread_create (&thread, &attr, start_routine, args) != 0) fatal_error("pthread_create() failed",0); - pthread_attr_destroy (&attr); + pthread_attr_destroy(&attr); return thread; } @@ -21,9 +21,8 @@ pthread_key_t current_vm_tls_key = 0; void init_platform_globals() { - if (pthread_key_create(¤t_vm_tls_key, NULL) != 0) + if(pthread_key_create(¤t_vm_tls_key, NULL) != 0) fatal_error("pthread_key_create() failed",0); - } void register_vm_with_thread(factor_vm *vm) @@ -187,8 +186,18 @@ static void sigaction_safe(int signum, const struct sigaction *act, struct sigac fatal_error("sigaction failed", 0); } -void unix_init_signals() +void factor_vm::unix_init_signals() { + signal_callstack_seg = new segment(callstack_size,false); + + stack_t signal_callstack; + signal_callstack.ss_sp = (void *)signal_callstack_seg->start; + signal_callstack.ss_size = signal_callstack_seg->size; + signal_callstack.ss_flags = 0; + + if(sigaltstack(&signal_callstack,(stack_t *)NULL) < 0) + fatal_error("sigaltstack() failed",0); + struct sigaction memory_sigaction; struct sigaction misc_sigaction; struct sigaction fpe_sigaction; @@ -197,7 +206,7 @@ void unix_init_signals() memset(&memory_sigaction,0,sizeof(struct sigaction)); sigemptyset(&memory_sigaction.sa_mask); memory_sigaction.sa_sigaction = memory_signal_handler; - memory_sigaction.sa_flags = SA_SIGINFO; + memory_sigaction.sa_flags = SA_SIGINFO | SA_ONSTACK; sigaction_safe(SIGBUS,&memory_sigaction,NULL); sigaction_safe(SIGSEGV,&memory_sigaction,NULL); @@ -205,14 +214,14 @@ void unix_init_signals() memset(&fpe_sigaction,0,sizeof(struct sigaction)); sigemptyset(&fpe_sigaction.sa_mask); fpe_sigaction.sa_sigaction = fpe_signal_handler; - fpe_sigaction.sa_flags = SA_SIGINFO; + fpe_sigaction.sa_flags = SA_SIGINFO | SA_ONSTACK; sigaction_safe(SIGFPE,&fpe_sigaction,NULL); memset(&misc_sigaction,0,sizeof(struct sigaction)); sigemptyset(&misc_sigaction.sa_mask); misc_sigaction.sa_sigaction = misc_signal_handler; - misc_sigaction.sa_flags = SA_SIGINFO; + misc_sigaction.sa_flags = SA_SIGINFO | SA_ONSTACK; sigaction_safe(SIGQUIT,&misc_sigaction,NULL); sigaction_safe(SIGILL,&misc_sigaction,NULL); diff --git a/vm/os-unix.hpp b/vm/os-unix.hpp index de60bbe15f..df6e0b4b3e 100644 --- a/vm/os-unix.hpp +++ b/vm/os-unix.hpp @@ -39,7 +39,6 @@ typedef pthread_t THREADHANDLE; THREADHANDLE start_thread(void *(*start_routine)(void *),void *args); inline static THREADHANDLE thread_id() { return pthread_self(); } -void unix_init_signals(); void signal_handler(int signal, siginfo_t* siginfo, void* uap); void dump_stack_signal(int signal, siginfo_t* siginfo, void* uap); diff --git a/vm/os-windows.cpp b/vm/os-windows.cpp index d69966567a..1ff1b174b5 100755 --- a/vm/os-windows.cpp +++ b/vm/os-windows.cpp @@ -143,4 +143,6 @@ void factor_vm::move_file(const vm_char *path1, const vm_char *path2) general_error(ERROR_IO,tag_fixnum(GetLastError()),false_object); } +void factor_vm::init_signals() {} + } diff --git a/vm/os-windows.hpp b/vm/os-windows.hpp index 92a3c73a99..020a506038 100755 --- a/vm/os-windows.hpp +++ b/vm/os-windows.hpp @@ -43,7 +43,6 @@ typedef wchar_t vm_char; /* Difference between Jan 1 00:00:00 1601 and Jan 1 00:00:00 1970 */ #define EPOCH_OFFSET 0x019db1ded53e8000LL -inline static void init_signals() {} inline static void early_init() {} u64 system_micros(); diff --git a/vm/vm.cpp b/vm/vm.cpp index 87bf47f290..e9ade19cc6 100755 --- a/vm/vm.cpp +++ b/vm/vm.cpp @@ -13,7 +13,8 @@ factor_vm::factor_vm() : gc_events(NULL), fep_disabled(false), full_output(false), - last_nano_count(0) + last_nano_count(0), + signal_callstack_seg(NULL) { primitive_reset_dispatch_stats(); } @@ -21,6 +22,11 @@ factor_vm::factor_vm() : factor_vm::~factor_vm() { delete_contexts(); + if(signal_callstack_seg) + { + delete signal_callstack_seg; + signal_callstack_seg = NULL; + } } } diff --git a/vm/vm.hpp b/vm/vm.hpp index 7a0b0fcd33..4402b64f41 100755 --- a/vm/vm.hpp +++ b/vm/vm.hpp @@ -107,6 +107,9 @@ struct factor_vm decrease */ u64 last_nano_count; + /* Stack for signal handlers, only used on Unix */ + segment *signal_callstack_seg; + // contexts context *new_context(); void delete_context(context *old_context); @@ -339,7 +342,7 @@ struct factor_vm template bool reallot_array_in_place_p(Array *array, cell capacity); template Array *reallot_array(Array *array_, cell capacity); - //debug + // debug void print_chars(string* str); void print_word(word* word, cell nesting); void print_factor_string(string* str); @@ -362,7 +365,7 @@ struct factor_vm void factorbug(); void primitive_die(); - //arrays + // arrays inline void set_array_nth(array *array, cell slot, cell value); array *allot_array(cell capacity, cell fill_); void primitive_array(); @@ -372,7 +375,7 @@ struct factor_vm void primitive_resize_array(); cell std_vector_to_array(std::vector &elements); - //strings + // strings cell string_nth(const string *str, cell index); void set_string_nth_fast(string *str, cell index, cell ch); void set_string_nth_slow(string *str_, cell index, cell ch); @@ -388,13 +391,13 @@ struct factor_vm void primitive_set_string_nth_fast(); void primitive_set_string_nth_slow(); - //booleans + // booleans cell tag_boolean(cell untagged) { return (untagged ? true_object : false_object); } - //byte arrays + // byte arrays byte_array *allot_byte_array(cell size); void primitive_byte_array(); void primitive_uninitialized_byte_array(); @@ -402,11 +405,11 @@ struct factor_vm template byte_array *byte_array_from_value(Type *value); - //tuples + // tuples void primitive_tuple(); void primitive_tuple_boa(); - //words + // words word *allot_word(cell name_, cell vocab_, cell hashcode_); void primitive_word(); void primitive_word_code(); @@ -417,7 +420,7 @@ struct factor_vm cell find_all_words(); void compile_all_words(); - //math + // math void primitive_bignum_to_fixnum(); void primitive_float_to_fixnum(); void primitive_fixnum_divint(); @@ -503,7 +506,7 @@ struct factor_vm // tagged template Type *untag_check(cell value); - //io + // io void init_c_io(); void io_error(); FILE* safe_fopen(char *filename, char *mode); @@ -526,7 +529,7 @@ struct factor_vm void primitive_fflush(); void primitive_fclose(); - //code_block + // code_block cell compute_entry_point_address(cell obj); cell compute_entry_point_pic_address(word *w, cell tagged_quot); cell compute_entry_point_pic_address(cell w_); @@ -563,11 +566,11 @@ struct factor_vm cell code_blocks(); void primitive_code_blocks(); - //callbacks + // callbacks void init_callbacks(cell size); void primitive_callback(); - //image + // image void init_objects(image_header *h); void load_data_heap(FILE *file, image_header *h, vm_parameters *p); void load_code_heap(FILE *file, image_header *h, vm_parameters *p); @@ -578,7 +581,7 @@ struct factor_vm void fixup_code(cell data_offset, cell code_offset); void load_image(vm_parameters *p); - //callstack + // callstack template void iterate_callstack_object(callstack *stack_, Iterator &iterator); void check_frame(stack_frame *frame); callstack *allot_callstack(cell size); @@ -598,7 +601,7 @@ struct factor_vm void primitive_set_innermost_stack_frame_quot(); template void iterate_callstack(context *ctx, Iterator &iterator); - //alien + // alien char *pinned_alien_offset(cell obj); cell allot_alien(cell delegate_, cell displacement); cell allot_alien(void *address); @@ -615,7 +618,7 @@ struct factor_vm cell from_small_struct(cell x, cell y, cell size); cell from_medium_struct(cell x1, cell x2, cell x3, cell x4, cell size); - //quotations + // quotations void primitive_jit_compile(); code_block *lazy_jit_compile_block(); void primitive_array_to_quotation(); @@ -630,7 +633,7 @@ struct factor_vm cell find_all_quotations(); void initialize_all_quotations(); - //dispatch + // dispatch cell search_lookup_alist(cell table, cell klass); cell search_lookup_hash(cell table, cell klass, cell hashcode); cell nth_superclass(tuple_layout *layout, fixnum echelon); @@ -645,7 +648,7 @@ struct factor_vm void primitive_reset_dispatch_stats(); void primitive_dispatch_stats(); - //inline cache + // inline cache void init_inline_caching(int max_size); void deallocate_inline_cache(cell return_address); cell determine_inline_cache_type(array *cache_entries); @@ -657,11 +660,11 @@ struct factor_vm void update_pic_transitions(cell pic_size); void *inline_cache_miss(cell return_address); - //entry points + // entry points void c_to_factor(cell quot); void unwind_native_frames(cell quot, stack_frame *to); - //factor + // factor void default_parameters(vm_parameters *p); bool factor_arg(const vm_char *str, const vm_char *arg, cell *value); void init_parameters_from_args(vm_parameters *p, int argc, vm_char **argv); @@ -685,6 +688,7 @@ struct factor_vm void *ffi_dlsym(dll *dll, symbol_char *symbol); void ffi_dlclose(dll *dll); void c_to_factor_toplevel(cell quot); + void init_signals(); // os-windows #if defined(WINDOWS) @@ -697,8 +701,10 @@ struct factor_vm void open_console(); LONG exception_handler(PEXCEPTION_POINTERS pe); #endif + #else // UNIX void dispatch_signal(void *uap, void (handler)()); + void unix_init_signals(); #endif #ifdef __APPLE__ @@ -707,7 +713,6 @@ struct factor_vm factor_vm(); ~factor_vm(); - }; extern std::map thread_vms;