This is the mail archive of the cygwin 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 01:39, Dave Korn wrote:
> On 24/02/2010 00:44, Christopher Faylor wrote:

>> Anyway, I've revisited this code, just like I knew I would, and have
>> added YA in a long series of tweaks which seems to fix your particular
>> problem.  The fix is in the latest snapshot.
>   :( I think I can see where the next problem is going to arise already.
>   If we move el to the front of the list each time, what's going to happen
> when we eventually return from LoadLibrary, and el.prev is still pointing at
> the now-deallocated stack frames where LoadLibrary created its temporary

  Confirmed.  Here's the SEH chain at the call to pthread_mutexattr_init:

> (gdb) x/xw 0x7ffde000
> 0x7ffde000:     0x0022ce68
> (gdb) x/2xw 0x0022ce68
> 0x22ce68:       0x0022c8b4      0x61028d70
> (gdb) x/2xw 0x0022c8b4
> 0x22c8b4:       0x0022cb4c      0x77fb7e64
> (gdb) x/2xw 0x0022cb4c
> 0x22cb4c:       0x0022cbf8      0x77fb7e64
> (gdb) x/2xw 0x0022cbf8
> 0x22cbf8:       0x0022ffe0      0x7c5c2160
> (gdb) x/2xw 0x0022ffe0
> 0x22ffe0:       0xffffffff      0x7c5c2160
> (gdb) print $esp
> $1 = (void *) 0x22c764

  At this point, the call stack looks roughly like main -> dlopen ->
LoadLibraryW -> DllMain -> dll_dllcrt0_1 -> dll::init (because the cygwin dll
is already initialised, we don't defer calling) -> dll static ctors ->
Mutex::Mutex -> pthread_mutexattr_init.  After this, we return from the Mutex
ctor, dll::init calls DllMain and then returns back to the OS loader code
which eventually returns via the tail of LoadLibrary and dlopen to main:

> (gdb) c
> Continuing.
> Breakpoint 6, main (argc=1, argv=0x659e18) at test.cpp:6
> 6         dlclose( dll );
> (gdb) print $esp
> $2 = (void *) 0x22cd00
> (gdb) x/xw 0x7ffde000
> 0x7ffde000:     0x0022ffe0
> (gdb) x/2xw 0x0022ffe0
> 0x22ffe0:       0xffffffff      0x7c5c2160
> (gdb)

  Our EH got uninstalled when the OS uninstalled its own handlers!  That makes
sense of course: when a function that has instantiated an
EXCEPTION_REGISTRATION record in automatic stack storage returns, it's just
going to assume that any deeper ones have already been unwound and look at its
own prev pointer and just set the head of the eh chain there.

  I think the answer lies here, in this comment in dll_dllcrt0_1:

>   /* Make sure that our exception handler is installed.
>      That should always be the case but this just makes sure.
>      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);

  Well, it may or may not already be installed, depending whether we got here
via dlopen or whether this is a statically-linked DLL being initialised at
process startup, and if it is already installed, it's not at the front of the
list.  So I figure the best bet would be to replace this call with a local
stack-frame-based exception registration record, which we'll unlink if we
return.  IOW, just the same thing as those OS-registered SEH frames are doing
when they unwind.  I'll report back later if it works.


Problem reports:
Unsubscribe info:

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