This is the mail archive of the cygwin-patches mailing list for the Cygwin project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Statically initialising pthread attributes in dynamic dlls.


On 24/02/2010 21:44, Christopher Faylor wrote:

> Hmm.  That would presumably cause the behavior that Dave Korn noted of
> removing the handler after FreeLibrary returns.  So you'd have to put it
> there and in dlclose.  

  The temporary handler in dll_dllcrt0_1 approach seems an awful lot simpler
and more reliable to me than all this tedious mucking about in hyperspace...
erm, I mean all this tedious unlinking and relinking the chain and hoping
nothing bad happens during the window when we have no handler installed at
all.  Why don't we just fix it this way instead?

winsup/cygwin/ChangeLog:

	* dll_init.cc (dll_dllcrt0_1): Install a temporary SEH frame instead
	of redirecting the global registration.
	* dlfcn.cc (dlopen): Revert last change rendered superfluous by the
	above.

    cheers,
      DaveK

Index: winsup/cygwin/dll_init.cc
===================================================================
RCS file: /cvs/src/src/winsup/cygwin/dll_init.cc,v
retrieving revision 1.70
diff -p -u -r1.70 dll_init.cc
--- winsup/cygwin/dll_init.cc	5 Feb 2010 15:05:22 -0000	1.70
+++ winsup/cygwin/dll_init.cc	25 Feb 2010 12:32:00 -0000
@@ -322,14 +322,51 @@ dll_dllcrt0_1 (VOID *x)
   per_process*& p = ((dllcrt0_info *)x)->p;
   int& res = ((dllcrt0_info *)x)->res;
 
-  /* Make sure that our exception handler is installed.
-     That should always be the case but this just makes sure.
+  /* Make sure that our exception handler is installed.  Those few
+     simple words unlock a not nearly so simple can of worms.
 
-     At some point, we may want to just remove this code since
-     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);
+     This function is part of every Cygwin-based DLL's C runtime
+     startup sequence, called from the DllMain implementation in
+     DECLARE_CYGWIN_DLL at process attach notification time.  This
+     can arise in one of two ways: at initial process startup when the
+     statically-linked DLLs are being mapped, or as a result of a call
+     to dlopen() at runtime.
+
+     In the first case, the cygwin DLL may not have been initialised
+     yet, and our exception handler may or may not yet be installed.
+     In the second case, it is definitely installed, but the OS runtime
+     loader has installed its own SEH handlers ahead of ours.
+
+     That's a problem; we need ours to be the first, not just for signal
+     handling (which is probably irrelevant, as you shouldn't try anything
+     too complex inside a DllMain function when the OS loader lock is held)
+     but also to support the sjfault-handling/verifyable_object mechanism.
+
+     Earlier versions of the code called _cygtls::init_exception_handler
+     here, but that is problematic.  There is only a single exception_list
+     member in the _cygtls class that we use to register our SEH handler,
+     and in order to reuse it to add at the head of the SEH chain, it would
+     either have to create a loop in the list, or unlink it from its original
+     earlier position in the list.  The former is disallowed by the SEH chain
+     validation performed for security reasons on modern versions of the OS;
+     the latter works fine, but it gets implicitly unlinked when we return 
+     from this function, as the OS loader removes its own frames, and the
+     main application then carries on without any SEH handler installed,
+     breaking the world.
+
+     We could try temporarily moving it to the head of the list, marking
+     the original position, and moving it back there before we return from
+     here, but the simplest solution is to just install a regular stack-
+     based EH frame right here, and unwind it when we leave.  (We don't want
+     to leave it to be implicitly unwound when the OS loader unwinds its
+     own frames, as there would be at least a short window while the SEH
+     chain was invalid.)  */
+
+  extern exception_list *_except_list asm ("%fs:0");
+  exception_list seh;
+  seh.handler = _cygtls::handle_exceptions;
+  seh.prev = _except_list;
+  _except_list = &seh;
 
   if (p == NULL)
     p = &__cygwin_user_data;
@@ -390,6 +427,9 @@ dll_dllcrt0_1 (VOID *x)
     res = -1;
   else
     res = (DWORD) d;
+
+  /* Finally unwind our SEH handler before returning.  */
+  _except_list = seh.prev;
 }
 
 /* OBSOLETE: This function is obsolete and will go away in the
Index: winsup/cygwin/dlfcn.cc
===================================================================
RCS file: /cvs/src/src/winsup/cygwin/dlfcn.cc,v
retrieving revision 1.44
diff -p -u -r1.44 dlfcn.cc
--- winsup/cygwin/dlfcn.cc	24 Feb 2010 08:03:44 -0000	1.44
+++ winsup/cygwin/dlfcn.cc	25 Feb 2010 12:32:00 -0000
@@ -109,9 +109,6 @@ dlopen (const char *name, int)
 
 	  ret = (void *) LoadLibraryW (path);
 
-	  /* In case it was removed by LoadLibrary. */
-	  _my_tls.init_exception_handler (_cygtls::handle_exceptions);
-
 	  /* Restore original cxx_malloc pointer. */
 	  __cygwin_user_data.cxx_malloc = tmp_malloc;
 

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]