On Thu, Jul 16, 2009 at 09:55:52PM +0200, Corinna Vinschen wrote: >On Jul 16 17:47, Dave Korn wrote: >> Corinna Vinschen wrote: >> >> > And that's what I get in the Perl testcase: >> > >> > (gdb) x/xw 0x7efdd000 >> > 0x7efdd000: 0x0088ce68 >> > (gdb) x/2xw 0x0088ce68 >> > 0x88ce68: 0x0088400c 0x6103ce20 <-- Cygwin exception handler >> > (gdb) x/2xw 0x0088400c >> > 0x88400c: 0x00000000 0x00000001 <-- Huh? >> > >> > This looks wrong, doesn't it? The question is now, how and why does >> > that happen? >> >> > Where's the 0x00000000 pointer coming from on 2008? Is it possible that >> > the OS overwrote the entry because it appears to be an address in Perl's >> > stack, so it's a potential security theat? >> >> The addresses are in the wrong order; SEH registration records should >> always nest in the same way as stack call frames, i.e. unwinding toward >> ascending memory addresses, but the second record is at a lower address than >> the first, so the chain has been mangled somehow. Perhaps that breaks an >> integrity check in the kernel? Where actually is $esp at the time; is the >> bogus one in an already-released frame below $esp? > >Seems so. $esp is 0x88c8c0. > >> You might want to try again with a watchpoint: >> >> watch *(unsigned int*)0x88ce68 >> >> ... and see how and where that head entry gets set up and whether it >> subsequently gets overwritten somehow. > >That was really helpful, Dave. Thank you! > >Here's the result: > >(gdb) br pthread_attr_init >Breakpoint 2 at 0x610f42dc: file >/home/corinna/src/cygwin/vanilla/winsup/cygwin/thread.cc, line 1909. >(gdb) watch *(unsigned int*)0x88ce68 >Hardware watchpoint 3: *(unsigned int *) 8965736 >(gdb) c >Continuing. >Hardware watchpoint 3: *(unsigned int *) 8965736 > >Old value = 8978372 >New value = 8929292 >_cygtls::init_exception_handler (this=0x88ce64, > eh=0x6103ce20 <_cygtls::handle_exceptions(_EXCEPTION_RECORD*, > _exception_lis >t*, _CONTEXT*, void*)>) > at /home/corinna/src/cygwin/vanilla/winsup/cygwin/cygtls.cc:244 >244 _except_list = ⪙ >Current language: auto; currently c++ >(gdb) p/x 8978372 >$1 = 0x88ffc4 >(gdb) p/x 8929292 >$2 = 0x88400c >(gdb) p $esp >$3 = (void *) 0x883e78 >(gdb) bt >#0 _cygtls::init_exception_handler (this=0x88ce64, > eh=0x6103ce20 <_cygtls::handle_exceptions(_EXCEPTION_RECORD*, > _exception_lis >t*, _CONTEXT*, void*)>) > at /home/corinna/src/cygwin/vanilla/winsup/cygwin/cygtls.cc:244 >#1 0x61033ff5 in dll_dllcrt0_1 (x=0x883edc) > at /home/corinna/src/cygwin/vanilla/winsup/cygwin/dll_init.cc:321 >#2 0x6103414f in dll_dllcrt0 (h=0x6eb70000, p=0x6eb79070) > at /home/corinna/src/cygwin/vanilla/winsup/cygwin/dll_init.cc:302 >#3 0x6eb77acf in _cygwin_dll_en...@12 () > from /usr/lib/perl5/5.10/i686-cygwin/auto/threads/threads.dll >^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ > >So this exception handler is installed as part of the Perl threads DLL >initialization. But appanrelty the address is not valid anymore when >leaving the DLL initialization. > >For testing I disabled the > > _my_tls.init_exception_handler (_cygtls::handle_exceptions); > >call in dll_init.cc:dll_dllcrt0_1() and re-ran the Perl testcase. >Now it runs fine: > > $ perl ./perlthread.pl > Testing threads... > I'm a thread! > Testing done > >Is it possible that we have to remove the exception handler before >dll_dllcrt0_1 returns?
Are you saying that perl not cleaning up after itself here? If so, that sounds like a perl bug. cgf -- Problem reports: http://cygwin.com/problems.html FAQ: http://cygwin.com/faq/ Documentation: http://cygwin.com/docs.html Unsubscribe info: http://cygwin.com/ml/#unsubscribe-simple