From 837a026a071dd0aded918f577e970ba6a7f1d223 Mon Sep 17 00:00:00 2001 From: cgf Date: Sat, 27 Feb 2010 06:36:31 +0000 Subject: [PATCH] * cygtls.h (_cygtls::init_exception_handler): Eliminate argument. (_cygtls::andreas): Convert to a pointer. (san): Convert to a real class with methods. Use a linked list to keep track of previous handlers on the "stack". (myfault): Rewrite to use new san class rather than calling directly into _cygtls. * cygtls.cc (_cygtls::init_exception_handler): Just assume that we're always using the standard exception handler. (_cygtls::init_thread): Reflect loss of argument to init_exception_handler. * dcrt0.cc (dll_crt0_1): Ditto. * dfcn.cc (dlopen): Ditto. (dlclose): Reset the exception handler after FreeLibrary. * dll_init.cc (dll_list::detach): Make sure that the exception handler is initialized before calling destructors. * exceptions.cc (_cygtls::handle_exceptions): Accommodate new andreas pointer. * thread.cc (verifyable_object_isvalid): Pass objectptr to faulted for explicit NULL pointer checking. * tlsoffsets.h: Regenerate. --- winsup/cygwin/ChangeLog | 23 ++++++++++++ winsup/cygwin/cygtls.cc | 8 ++--- winsup/cygwin/cygtls.h | 88 +++++++++++++++++++++++---------------------- winsup/cygwin/dcrt0.cc | 2 +- winsup/cygwin/dlfcn.cc | 15 ++++++-- winsup/cygwin/dll_init.cc | 4 ++- winsup/cygwin/exceptions.cc | 4 +-- winsup/cygwin/thread.cc | 4 +-- winsup/cygwin/tlsoffsets.h | 66 +++++++++++++++++----------------- 9 files changed, 125 insertions(+), 89 deletions(-) diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index 72f8fa6584..557cf373d9 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,5 +1,28 @@ 2010-02-26 Christopher Faylor + * cygtls.h (_cygtls::init_exception_handler): Eliminate argument. + (_cygtls::andreas): Convert to a pointer. + (san): Convert to a real class with methods. Use a linked list to + keep track of previous handlers on the "stack". + (myfault): Rewrite to use new san class rather than calling directly + into _cygtls. + * cygtls.cc (_cygtls::init_exception_handler): Just assume that we're + always using the standard exception handler. + (_cygtls::init_thread): Reflect loss of argument to + init_exception_handler. + * dcrt0.cc (dll_crt0_1): Ditto. + * dfcn.cc (dlopen): Ditto. + (dlclose): Reset the exception handler after FreeLibrary. + * dll_init.cc (dll_list::detach): Make sure that the exception handler + is initialized before calling destructors. + * exceptions.cc (_cygtls::handle_exceptions): Accommodate new andreas + pointer. + * thread.cc (verifyable_object_isvalid): Pass objectptr to faulted for + explicit NULL pointer checking. + * tlsoffsets.h: Regenerate. + +2010-02-26 Christopher Faylor + * mkimport: cd away from temp directory or Windows will have problems removing the directory. diff --git a/winsup/cygwin/cygtls.cc b/winsup/cygwin/cygtls.cc index 32227e2877..979d968512 100644 --- a/winsup/cygwin/cygtls.cc +++ b/winsup/cygwin/cygtls.cc @@ -91,7 +91,7 @@ _cygtls::init_thread (void *x, DWORD (*func) (void *, void *)) locals.process_logmask = LOG_UPTO (LOG_DEBUG); /* Initialize this thread's ability to respond to things like SIGSEGV or SIGFPE. */ - init_exception_handler (handle_exceptions); + init_exception_handler (); } thread_id = GetCurrentThreadId (); @@ -226,7 +226,7 @@ _cygtls::set_siginfo (sigpacket *pack) extern exception_list *_except_list asm ("%fs:0"); void -_cygtls::init_exception_handler (exception_handler *eh) +_cygtls::init_exception_handler () { /* Here in the distant past of 17-Jul-2009, we had an issue where Windows 2008 became YA perplexed because the cygwin exception handler was added @@ -249,7 +249,7 @@ _cygtls::init_exception_handler (exception_handler *eh) the old exception handler from the list and add it to the beginning. The next step will probably be to call this function at various points - in cygwin (like from _cygtls::setup_fault maybe) to absoltely ensure that + in cygwin (like from _cygtls::setup_fault maybe) to absolutely ensure that we have control. For now, however, this seems good enough. (cgf 2010-02-23) */ @@ -275,7 +275,7 @@ _cygtls::init_exception_handler (exception_handler *eh) Windows 2008, which irremediably gets into an endless loop, taking 100% CPU. That's why we reverted to a normal SEH chain and changed the way the exception handler returns to the application. */ - el.handler = eh; + el.handler = handle_exceptions; el.prev = _except_list; _except_list = ⪙ } diff --git a/winsup/cygwin/cygtls.h b/winsup/cygwin/cygtls.h index f05379f48a..489e809294 100644 --- a/winsup/cygwin/cygtls.h +++ b/winsup/cygwin/cygtls.h @@ -53,6 +53,7 @@ public: void destroy (); friend class tmp_pathbuf; friend class _cygtls; + friend class san; }; class unionent @@ -157,14 +158,6 @@ typedef struct struct_waitq HANDLE thread_ev; } waitq; -typedef struct -{ - void *_myfault; - int _myfault_errno; - int _myfault_c_cnt; - int _myfault_w_cnt; -} san; - /* Changes to the below structure may require acompanying changes to the very simple parser in the perl script 'gentls_offsets' (<<-- start parsing here). The union in this structure is used to force alignment between the version @@ -205,7 +198,7 @@ struct _cygtls }; struct _local_storage locals; class cygthread *_ctinfo; - san andreas; + class san *andreas; waitq wq; int sig; unsigned incyg; @@ -239,7 +232,7 @@ struct _cygtls /* exception handling */ static int handle_exceptions (EXCEPTION_RECORD *, exception_list *, CONTEXT *, void *); bool inside_kernel (CONTEXT *); - void init_exception_handler (int (*) (EXCEPTION_RECORD *, exception_list *, CONTEXT *, void*)); + void init_exception_handler () __attribute__ ((regparm(1))); void signal_exit (int) __attribute__ ((noreturn, regparm(2))); void copy_context (CONTEXT *) __attribute__ ((regparm(2))); void signal_debugger (int) __attribute__ ((regparm(2))); @@ -256,34 +249,6 @@ struct _cygtls void lock () __attribute__ ((regparm (1))); void unlock () __attribute__ ((regparm (1))); bool locked () __attribute__ ((regparm (1))); - void*& fault_guarded () {return andreas._myfault;} - void return_from_fault () - { - if (andreas._myfault_errno) - set_errno (andreas._myfault_errno); - /* Restore tls_pathbuf counters in case of error. */ - locals.pathbufs.c_cnt = andreas._myfault_c_cnt; - locals.pathbufs.w_cnt = andreas._myfault_w_cnt; - __ljfault ((int *) andreas._myfault, 1); - } - int setup_fault (jmp_buf j, san& old_j, int myerrno) __attribute__ ((always_inline)) - { - old_j._myfault = andreas._myfault; - old_j._myfault_errno = andreas._myfault_errno; - old_j._myfault_c_cnt = andreas._myfault_c_cnt; - old_j._myfault_w_cnt = andreas._myfault_w_cnt; - andreas._myfault = (void *) j; - andreas._myfault_errno = myerrno; - /* Save tls_pathbuf counters. */ - andreas._myfault_c_cnt = locals.pathbufs.c_cnt; - andreas._myfault_w_cnt = locals.pathbufs.w_cnt; - return __sjfault (j); - } - void reset_fault (san& old_j) __attribute__ ((always_inline)) - { - andreas._myfault = old_j._myfault; - andreas._myfault_errno = old_j._myfault_errno; - } /*gentls_offsets*/ }; #pragma pack(pop) @@ -298,15 +263,54 @@ extern char *_tlstop __asm__ ("%fs:8"); extern _cygtls *_main_tls; extern _cygtls *_sig_tls; +class san +{ + san *_clemente; + jmp_buf _context; + int _errno; + int _c_cnt; + int _w_cnt; +public: + int setup (int myerrno = 0) __attribute__ ((always_inline)) + { + _clemente = _my_tls.andreas; + _my_tls.andreas = this; + _errno = myerrno; + _c_cnt = _my_tls.locals.pathbufs.c_cnt; + _w_cnt = _my_tls.locals.pathbufs.w_cnt; + return __sjfault (_context); + } + void leave () __attribute__ ((always_inline)) + { + if (_errno) + set_errno (_errno); + /* Restore tls_pathbuf counters in case of error. */ + _my_tls.locals.pathbufs.c_cnt = _c_cnt; + _my_tls.locals.pathbufs.w_cnt = _w_cnt; + __ljfault (_context, 1); + } + void reset () __attribute__ ((always_inline)) + { + _my_tls.andreas = _clemente; + } +}; + class myfault { - jmp_buf buf; san sebastian; public: - ~myfault () __attribute__ ((always_inline)) { _my_tls.reset_fault (sebastian); } - inline int faulted (int myerrno = 0) __attribute__ ((always_inline)) + ~myfault () __attribute__ ((always_inline)) { sebastian.reset (); } + inline int faulted () __attribute__ ((always_inline)) + { + return sebastian.setup (0); + } + inline int faulted (void const *obj, int myerrno = 0) __attribute__ ((always_inline)) + { + return (!obj || !(*(const char **)obj)) || sebastian.setup (myerrno); + } + inline int faulted (int myerrno) __attribute__ ((always_inline)) { - return _my_tls.setup_fault (buf, sebastian, myerrno); + return sebastian.setup (myerrno); } }; diff --git a/winsup/cygwin/dcrt0.cc b/winsup/cygwin/dcrt0.cc index 6745f096e7..78bab04712 100644 --- a/winsup/cygwin/dcrt0.cc +++ b/winsup/cygwin/dcrt0.cc @@ -823,7 +823,7 @@ dll_crt0_1 (void *) { _tlsbase = (char *) fork_info->stackbottom; _tlstop = (char *) fork_info->stacktop; - _my_tls.init_exception_handler (_cygtls::handle_exceptions); + _my_tls.init_exception_handler (); } longjmp (fork_info->jmp, true); diff --git a/winsup/cygwin/dlfcn.cc b/winsup/cygwin/dlfcn.cc index a1087dba20..77d26f2435 100644 --- a/winsup/cygwin/dlfcn.cc +++ b/winsup/cygwin/dlfcn.cc @@ -110,7 +110,7 @@ dlopen (const char *name, int) ret = (void *) LoadLibraryW (path); /* In case it was removed by LoadLibrary. */ - _my_tls.init_exception_handler (_cygtls::handle_exceptions); + _my_tls.init_exception_handler (); /* Restore original cxx_malloc pointer. */ __cygwin_user_data.cxx_malloc = tmp_malloc; @@ -160,9 +160,18 @@ dlsym (void *handle, const char *name) int dlclose (void *handle) { - int ret = -1; - if (handle == GetModuleHandle (NULL) || FreeLibrary ((HMODULE) handle)) + int ret; + if (handle == GetModuleHandle (NULL)) ret = 0; + else + { + if (FreeLibrary ((HMODULE) handle)) + ret = 0; + else + ret = -1; + /* In case it was removed by FreeLibrary */ + _my_tls.init_exception_handler (); + } if (ret) set_dl_error ("dlclose"); return ret; diff --git a/winsup/cygwin/dll_init.cc b/winsup/cygwin/dll_init.cc index 055b1060f2..8fef9d8b19 100644 --- a/winsup/cygwin/dll_init.cc +++ b/winsup/cygwin/dll_init.cc @@ -169,6 +169,8 @@ dll_list::detach (void *retaddr) system_printf ("WARNING: trying to detach an already detached dll ..."); if (--d->count == 0) { + /* Make sure our exception handler is enabled for destructors */ + _my_tls.init_exception_handler (); __cxa_finalize (d); d->run_dtors (); d->prev->next = d->next; @@ -329,7 +331,7 @@ dll_dllcrt0_1 (VOID *x) the exception handler should be guaranteed to be installed. I'm leaving it in until potentially after the release of 1.7.1 */ - _my_tls.init_exception_handler (_cygtls::handle_exceptions); + _my_tls.init_exception_handler (); if (p == NULL) p = &__cygwin_user_data; diff --git a/winsup/cygwin/exceptions.cc b/winsup/cygwin/exceptions.cc index e1bb7056cd..978fd77299 100644 --- a/winsup/cygwin/exceptions.cc +++ b/winsup/cygwin/exceptions.cc @@ -622,8 +622,8 @@ _cygtls::handle_exceptions (EXCEPTION_RECORD *e, exception_list *frame, CONTEXT break; } - if (me.fault_guarded ()) - me.return_from_fault (); + if (me.andreas) + me.andreas->leave (); /* Return from a "san" caught fault */ me.copy_context (in); diff --git a/winsup/cygwin/thread.cc b/winsup/cygwin/thread.cc index 474f6bd2d7..20eb95dfa0 100644 --- a/winsup/cygwin/thread.cc +++ b/winsup/cygwin/thread.cc @@ -124,9 +124,7 @@ verifyable_object_isvalid (void const *objectptr, thread_magic_t magic, void *st void *static_ptr2, void *static_ptr3) { myfault efault; - /* Check for NULL pointer specifically since it is a cheap test and avoids the - overhead of setting up the fault handler. */ - if (!objectptr || efault.faulted ()) + if (efault.faulted (objectptr)) return INVALID_OBJECT; verifyable_object **object = (verifyable_object **) objectptr; diff --git a/winsup/cygwin/tlsoffsets.h b/winsup/cygwin/tlsoffsets.h index cdc423deff..319469af54 100644 --- a/winsup/cygwin/tlsoffsets.h +++ b/winsup/cygwin/tlsoffsets.h @@ -1,6 +1,6 @@ //;# autogenerated: Do not edit. -//; $tls::sizeof__cygtls = 4324; +//; $tls::sizeof__cygtls = 4312; //; $tls::func = -12700; //; $tls::pfunc = 0; //; $tls::el = -12696; @@ -43,22 +43,22 @@ //; $tls::p_ctinfo = 3228; //; $tls::andreas = -9468; //; $tls::pandreas = 3232; -//; $tls::wq = -9452; -//; $tls::pwq = 3248; -//; $tls::sig = -9424; -//; $tls::psig = 3276; -//; $tls::incyg = -9420; -//; $tls::pincyg = 3280; -//; $tls::spinning = -9416; -//; $tls::pspinning = 3284; -//; $tls::stacklock = -9412; -//; $tls::pstacklock = 3288; -//; $tls::stackptr = -9408; -//; $tls::pstackptr = 3292; -//; $tls::stack = -9404; -//; $tls::pstack = 3296; -//; $tls::initialized = -8380; -//; $tls::pinitialized = 4320; +//; $tls::wq = -9464; +//; $tls::pwq = 3236; +//; $tls::sig = -9436; +//; $tls::psig = 3264; +//; $tls::incyg = -9432; +//; $tls::pincyg = 3268; +//; $tls::spinning = -9428; +//; $tls::pspinning = 3272; +//; $tls::stacklock = -9424; +//; $tls::pstacklock = 3276; +//; $tls::stackptr = -9420; +//; $tls::pstackptr = 3280; +//; $tls::stack = -9416; +//; $tls::pstack = 3284; +//; $tls::initialized = -8392; +//; $tls::pinitialized = 4308; //; __DATA__ #define tls_func (-12700) @@ -103,19 +103,19 @@ #define tls_p_ctinfo (3228) #define tls_andreas (-9468) #define tls_pandreas (3232) -#define tls_wq (-9452) -#define tls_pwq (3248) -#define tls_sig (-9424) -#define tls_psig (3276) -#define tls_incyg (-9420) -#define tls_pincyg (3280) -#define tls_spinning (-9416) -#define tls_pspinning (3284) -#define tls_stacklock (-9412) -#define tls_pstacklock (3288) -#define tls_stackptr (-9408) -#define tls_pstackptr (3292) -#define tls_stack (-9404) -#define tls_pstack (3296) -#define tls_initialized (-8380) -#define tls_pinitialized (4320) +#define tls_wq (-9464) +#define tls_pwq (3236) +#define tls_sig (-9436) +#define tls_psig (3264) +#define tls_incyg (-9432) +#define tls_pincyg (3268) +#define tls_spinning (-9428) +#define tls_pspinning (3272) +#define tls_stacklock (-9424) +#define tls_pstacklock (3276) +#define tls_stackptr (-9420) +#define tls_pstackptr (3280) +#define tls_stack (-9416) +#define tls_pstack (3284) +#define tls_initialized (-8392) +#define tls_pinitialized (4308) -- 2.11.0