* 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.
This commit is contained in:
Christopher Faylor 2010-02-26 21:36:31 +00:00
parent b6336c95b4
commit d5d5bf4dd5
9 changed files with 125 additions and 89 deletions

View File

@ -1,3 +1,26 @@
2010-02-26 Christopher Faylor <me+cygwin@cgf.cx>
* 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 <me+cygwin@cgf.cx> 2010-02-26 Christopher Faylor <me+cygwin@cgf.cx>
* mkimport: cd away from temp directory or Windows will have problems * mkimport: cd away from temp directory or Windows will have problems

View File

@ -91,7 +91,7 @@ _cygtls::init_thread (void *x, DWORD (*func) (void *, void *))
locals.process_logmask = LOG_UPTO (LOG_DEBUG); locals.process_logmask = LOG_UPTO (LOG_DEBUG);
/* Initialize this thread's ability to respond to things like /* Initialize this thread's ability to respond to things like
SIGSEGV or SIGFPE. */ SIGSEGV or SIGFPE. */
init_exception_handler (handle_exceptions); init_exception_handler ();
} }
thread_id = GetCurrentThreadId (); thread_id = GetCurrentThreadId ();
@ -226,7 +226,7 @@ _cygtls::set_siginfo (sigpacket *pack)
extern exception_list *_except_list asm ("%fs:0"); extern exception_list *_except_list asm ("%fs:0");
void 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 /* 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 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 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 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. we have control. For now, however, this seems good enough.
(cgf 2010-02-23) (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% 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 CPU. That's why we reverted to a normal SEH chain and changed the way
the exception handler returns to the application. */ the exception handler returns to the application. */
el.handler = eh; el.handler = handle_exceptions;
el.prev = _except_list; el.prev = _except_list;
_except_list = &el; _except_list = &el;
} }

View File

@ -53,6 +53,7 @@ public:
void destroy (); void destroy ();
friend class tmp_pathbuf; friend class tmp_pathbuf;
friend class _cygtls; friend class _cygtls;
friend class san;
}; };
class unionent class unionent
@ -157,14 +158,6 @@ typedef struct struct_waitq
HANDLE thread_ev; HANDLE thread_ev;
} waitq; } 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 /* Changes to the below structure may require acompanying changes to the very
simple parser in the perl script 'gentls_offsets' (<<-- start parsing here). simple parser in the perl script 'gentls_offsets' (<<-- start parsing here).
The union in this structure is used to force alignment between the version The union in this structure is used to force alignment between the version
@ -205,7 +198,7 @@ struct _cygtls
}; };
struct _local_storage locals; struct _local_storage locals;
class cygthread *_ctinfo; class cygthread *_ctinfo;
san andreas; class san *andreas;
waitq wq; waitq wq;
int sig; int sig;
unsigned incyg; unsigned incyg;
@ -239,7 +232,7 @@ struct _cygtls
/* exception handling */ /* exception handling */
static int handle_exceptions (EXCEPTION_RECORD *, exception_list *, CONTEXT *, void *); static int handle_exceptions (EXCEPTION_RECORD *, exception_list *, CONTEXT *, void *);
bool inside_kernel (CONTEXT *); 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 signal_exit (int) __attribute__ ((noreturn, regparm(2)));
void copy_context (CONTEXT *) __attribute__ ((regparm(2))); void copy_context (CONTEXT *) __attribute__ ((regparm(2)));
void signal_debugger (int) __attribute__ ((regparm(2))); void signal_debugger (int) __attribute__ ((regparm(2)));
@ -256,34 +249,6 @@ struct _cygtls
void lock () __attribute__ ((regparm (1))); void lock () __attribute__ ((regparm (1)));
void unlock () __attribute__ ((regparm (1))); void unlock () __attribute__ ((regparm (1)));
bool locked () __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*/ /*gentls_offsets*/
}; };
#pragma pack(pop) #pragma pack(pop)
@ -298,15 +263,54 @@ extern char *_tlstop __asm__ ("%fs:8");
extern _cygtls *_main_tls; extern _cygtls *_main_tls;
extern _cygtls *_sig_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 class myfault
{ {
jmp_buf buf;
san sebastian; san sebastian;
public: public:
~myfault () __attribute__ ((always_inline)) { _my_tls.reset_fault (sebastian); } ~myfault () __attribute__ ((always_inline)) { sebastian.reset (); }
inline int faulted (int myerrno = 0) __attribute__ ((always_inline)) inline int faulted () __attribute__ ((always_inline))
{ {
return _my_tls.setup_fault (buf, sebastian, myerrno); 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 sebastian.setup (myerrno);
} }
}; };

View File

@ -823,7 +823,7 @@ dll_crt0_1 (void *)
{ {
_tlsbase = (char *) fork_info->stackbottom; _tlsbase = (char *) fork_info->stackbottom;
_tlstop = (char *) fork_info->stacktop; _tlstop = (char *) fork_info->stacktop;
_my_tls.init_exception_handler (_cygtls::handle_exceptions); _my_tls.init_exception_handler ();
} }
longjmp (fork_info->jmp, true); longjmp (fork_info->jmp, true);

View File

@ -110,7 +110,7 @@ dlopen (const char *name, int)
ret = (void *) LoadLibraryW (path); ret = (void *) LoadLibraryW (path);
/* In case it was removed by LoadLibrary. */ /* 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. */ /* Restore original cxx_malloc pointer. */
__cygwin_user_data.cxx_malloc = tmp_malloc; __cygwin_user_data.cxx_malloc = tmp_malloc;
@ -160,9 +160,18 @@ dlsym (void *handle, const char *name)
int int
dlclose (void *handle) dlclose (void *handle)
{ {
int ret = -1; int ret;
if (handle == GetModuleHandle (NULL) || FreeLibrary ((HMODULE) handle)) if (handle == GetModuleHandle (NULL))
ret = 0; 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) if (ret)
set_dl_error ("dlclose"); set_dl_error ("dlclose");
return ret; return ret;

View File

@ -169,6 +169,8 @@ dll_list::detach (void *retaddr)
system_printf ("WARNING: trying to detach an already detached dll ..."); system_printf ("WARNING: trying to detach an already detached dll ...");
if (--d->count == 0) if (--d->count == 0)
{ {
/* Make sure our exception handler is enabled for destructors */
_my_tls.init_exception_handler ();
__cxa_finalize (d); __cxa_finalize (d);
d->run_dtors (); d->run_dtors ();
d->prev->next = d->next; d->prev->next = d->next;
@ -329,7 +331,7 @@ dll_dllcrt0_1 (VOID *x)
the exception handler should be guaranteed to be installed. the exception handler should be guaranteed to be installed.
I'm leaving it in until potentially after the release of I'm leaving it in until potentially after the release of
1.7.1 */ 1.7.1 */
_my_tls.init_exception_handler (_cygtls::handle_exceptions); _my_tls.init_exception_handler ();
if (p == NULL) if (p == NULL)
p = &__cygwin_user_data; p = &__cygwin_user_data;

View File

@ -622,8 +622,8 @@ _cygtls::handle_exceptions (EXCEPTION_RECORD *e, exception_list *frame, CONTEXT
break; break;
} }
if (me.fault_guarded ()) if (me.andreas)
me.return_from_fault (); me.andreas->leave (); /* Return from a "san" caught fault */
me.copy_context (in); me.copy_context (in);

View File

@ -124,9 +124,7 @@ verifyable_object_isvalid (void const *objectptr, thread_magic_t magic, void *st
void *static_ptr2, void *static_ptr3) void *static_ptr2, void *static_ptr3)
{ {
myfault efault; myfault efault;
/* Check for NULL pointer specifically since it is a cheap test and avoids the if (efault.faulted (objectptr))
overhead of setting up the fault handler. */
if (!objectptr || efault.faulted ())
return INVALID_OBJECT; return INVALID_OBJECT;
verifyable_object **object = (verifyable_object **) objectptr; verifyable_object **object = (verifyable_object **) objectptr;

View File

@ -1,6 +1,6 @@
//;# autogenerated: Do not edit. //;# autogenerated: Do not edit.
//; $tls::sizeof__cygtls = 4324; //; $tls::sizeof__cygtls = 4312;
//; $tls::func = -12700; //; $tls::func = -12700;
//; $tls::pfunc = 0; //; $tls::pfunc = 0;
//; $tls::el = -12696; //; $tls::el = -12696;
@ -43,22 +43,22 @@
//; $tls::p_ctinfo = 3228; //; $tls::p_ctinfo = 3228;
//; $tls::andreas = -9468; //; $tls::andreas = -9468;
//; $tls::pandreas = 3232; //; $tls::pandreas = 3232;
//; $tls::wq = -9452; //; $tls::wq = -9464;
//; $tls::pwq = 3248; //; $tls::pwq = 3236;
//; $tls::sig = -9424; //; $tls::sig = -9436;
//; $tls::psig = 3276; //; $tls::psig = 3264;
//; $tls::incyg = -9420; //; $tls::incyg = -9432;
//; $tls::pincyg = 3280; //; $tls::pincyg = 3268;
//; $tls::spinning = -9416; //; $tls::spinning = -9428;
//; $tls::pspinning = 3284; //; $tls::pspinning = 3272;
//; $tls::stacklock = -9412; //; $tls::stacklock = -9424;
//; $tls::pstacklock = 3288; //; $tls::pstacklock = 3276;
//; $tls::stackptr = -9408; //; $tls::stackptr = -9420;
//; $tls::pstackptr = 3292; //; $tls::pstackptr = 3280;
//; $tls::stack = -9404; //; $tls::stack = -9416;
//; $tls::pstack = 3296; //; $tls::pstack = 3284;
//; $tls::initialized = -8380; //; $tls::initialized = -8392;
//; $tls::pinitialized = 4320; //; $tls::pinitialized = 4308;
//; __DATA__ //; __DATA__
#define tls_func (-12700) #define tls_func (-12700)
@ -103,19 +103,19 @@
#define tls_p_ctinfo (3228) #define tls_p_ctinfo (3228)
#define tls_andreas (-9468) #define tls_andreas (-9468)
#define tls_pandreas (3232) #define tls_pandreas (3232)
#define tls_wq (-9452) #define tls_wq (-9464)
#define tls_pwq (3248) #define tls_pwq (3236)
#define tls_sig (-9424) #define tls_sig (-9436)
#define tls_psig (3276) #define tls_psig (3264)
#define tls_incyg (-9420) #define tls_incyg (-9432)
#define tls_pincyg (3280) #define tls_pincyg (3268)
#define tls_spinning (-9416) #define tls_spinning (-9428)
#define tls_pspinning (3284) #define tls_pspinning (3272)
#define tls_stacklock (-9412) #define tls_stacklock (-9424)
#define tls_pstacklock (3288) #define tls_pstacklock (3276)
#define tls_stackptr (-9408) #define tls_stackptr (-9420)
#define tls_pstackptr (3292) #define tls_pstackptr (3280)
#define tls_stack (-9404) #define tls_stack (-9416)
#define tls_pstack (3296) #define tls_pstack (3284)
#define tls_initialized (-8380) #define tls_initialized (-8392)
#define tls_pinitialized (4320) #define tls_pinitialized (4308)