From: Nikodemus S. <de...@us...> - 2004-09-14 18:11:37
|
Update of /cvsroot/sbcl/sbcl/src/runtime In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv15373/src/runtime Modified Files: interrupt.c validate.c validate.h Log Message: 0.8.14.24: En Garde! * Robuster control stack exhaustion handling: automagically reprotect the guard-page after enough stack has unwound. * Simple stress tests for this. Index: interrupt.c =================================================================== RCS file: /cvsroot/sbcl/sbcl/src/runtime/interrupt.c,v retrieving revision 1.62 retrieving revision 1.63 diff -u -d -r1.62 -r1.63 --- interrupt.c 16 Aug 2004 18:19:15 -0000 1.62 +++ interrupt.c 14 Sep 2004 18:11:25 -0000 1.63 @@ -701,17 +701,31 @@ boolean handle_control_stack_guard_triggered(os_context_t *context,void *addr){ struct thread *th=arch_os_get_current_thread(); + /* note the os_context hackery here. When the signal handler returns, * it won't go back to what it was doing ... */ - if(addr>=(void *)CONTROL_STACK_GUARD_PAGE(th) && - addr<(void *)(CONTROL_STACK_GUARD_PAGE(th)+os_vm_page_size)) { - /* we hit the end of the control stack. disable protection - * temporarily so the error handler has some headroom */ - protect_control_stack_guard_page(th->pid,0L); - - arrange_return_to_lisp_function - (context, SymbolFunction(CONTROL_STACK_EXHAUSTED_ERROR)); - return 1; + if(addr >= CONTROL_STACK_GUARD_PAGE(th) && + addr < CONTROL_STACK_GUARD_PAGE(th) + os_vm_page_size) { + /* We hit the end of the control stack: disable guard page + * protection so the error handler has some headroom, protect the + * previous page so that we can catch returns from the guard page + * and restore it. */ + protect_control_stack_guard_page(th->pid,0); + protect_control_stack_return_guard_page(th->pid,1); + + arrange_return_to_lisp_function + (context, SymbolFunction(CONTROL_STACK_EXHAUSTED_ERROR)); + return 1; + } + else if(addr >= CONTROL_STACK_RETURN_GUARD_PAGE(th) && + addr < CONTROL_STACK_RETURN_GUARD_PAGE(th) + os_vm_page_size) { + /* We're returning from the guard page: reprotect it, and + * unprotect this one. This works even if we somehow missed + * the return-guard-page, and hit it on our way to new + * exhaustion instead. */ + protect_control_stack_guard_page(th->pid,1); + protect_control_stack_return_guard_page(th->pid,0); + return 1; } else return 0; } Index: validate.c =================================================================== RCS file: /cvsroot/sbcl/sbcl/src/runtime/validate.c,v retrieving revision 1.21 retrieving revision 1.22 diff -u -d -r1.21 -r1.22 --- validate.c 9 Sep 2004 12:10:15 -0000 1.21 +++ validate.c 14 Sep 2004 18:11:25 -0000 1.22 @@ -69,3 +69,9 @@ (OS_VM_PROT_READ|OS_VM_PROT_EXECUTE) : OS_VM_PROT_ALL); } +void protect_control_stack_return_guard_page(pid_t t_id, int protect_p) { + struct thread *th = find_thread_by_pid(t_id); + os_protect(CONTROL_STACK_RETURN_GUARD_PAGE(th), + os_vm_page_size,protect_p ? + (OS_VM_PROT_READ|OS_VM_PROT_EXECUTE) : OS_VM_PROT_ALL); +} Index: validate.h =================================================================== RCS file: /cvsroot/sbcl/sbcl/src/runtime/validate.h,v retrieving revision 1.11 retrieving revision 1.12 diff -u -d -r1.11 -r1.12 --- validate.h 9 Sep 2004 12:10:15 -0000 1.11 +++ validate.h 14 Sep 2004 18:11:25 -0000 1.12 @@ -27,13 +27,15 @@ #include <thread.h> #ifdef LISP_FEATURE_STACK_GROWS_DOWNWARD_NOT_UPWARD #define CONTROL_STACK_GUARD_PAGE(th) ((void *)(th->control_stack_start)) +#define CONTROL_STACK_RETURN_GUARD_PAGE(th) (CONTROL_STACK_GUARD_PAGE(th) + os_vm_page_size) #else -#define CONTROL_STACK_GUARD_PAGE(th) \ - (((void *)(th->control_stack_end)) - os_vm_page_size) +#define CONTROL_STACK_GUARD_PAGE(th) (((void *)(th->control_stack_end)) - os_vm_page_size) +#define CONTROL_STACK_RETURN_GUARD_PAGE(th) (CONTROL_STACK_GUARD_PAGE(th) - os_vm_page_size) #endif extern void validate(void); extern void protect_control_stack_guard_page(pid_t t_id, int protect_p); +extern void protect_control_stack_return_guard_page(pid_t t_id, int protect_p); #endif /* note for anyone trying to port an architecture's support files |