http://bugs.winehq.org/show_bug.cgi?id=24018
Anastasius Focht focht@gmx.net changed:
What |Removed |Added ---------------------------------------------------------------------------- CC| |focht@gmx.net
--- Comment #7 from Anastasius Focht focht@gmx.net 2013-05-05 07:49:57 CDT --- Hello folks,
from comment #5 console log you can reproduce it manually by running:
--- snip --- $ wine "C:\cygwin\bin\bash.exe" --norc --noprofile "/etc/postinstall/000-cygwin-post-install.sh" --- snip ---
Trace of child "bash" process with +virtual:
--- snip --- ... 0027:trace:virtual:map_view got mem in reserved area 0x490000-0x690000 0027:trace:virtual:VIRTUAL_DumpView View: 0x490000 - 0x68ffff (valloc) 0027:trace:virtual:VIRTUAL_DumpView 0x490000 - 0x68ffff c-rw- 0027:trace:virtual:create_view forcing exec permission on 0x490000-0x68ffff 0027:trace:virtual:VIRTUAL_SetProt 0x490000-0x490fff c---- 0027:trace:virtual:VIRTUAL_DumpView View: 0x490000 - 0x68ffff (valloc) 0027:trace:virtual:VIRTUAL_DumpView 0x490000 - 0x490fff c---- 0027:trace:virtual:VIRTUAL_DumpView 0x491000 - 0x68ffff c-rw- 0027:trace:virtual:VIRTUAL_SetProt 0x491000-0x491fff cgrw- 0027:trace:virtual:VIRTUAL_DumpView View: 0x490000 - 0x68ffff (valloc) 0027:trace:virtual:VIRTUAL_DumpView 0x490000 - 0x490fff c---- 0027:trace:virtual:VIRTUAL_DumpView 0x491000 - 0x491fff cgrw- 0027:trace:virtual:VIRTUAL_DumpView 0x492000 - 0x68ffff c-rw- 0024:Ret KERNEL32.CreateProcessW() retval=00000001 ret=61077c03 ... 0027:Starting process L"C:\cygwin\bin\bash.exe" (entryproc=0x401000) 0027:Call KERNEL32.GetModuleHandleA(00000000) ret=00465ab6 0027:Ret KERNEL32.GetModuleHandleA() retval=00400000 ret=00465ab6 0027:trace:virtual:VIRTUAL_SetProt 0x491000-0x491fff c-rw- 0027:trace:virtual:VIRTUAL_SetProt forcing exec permission on 0x491000-0x491fff 0027:trace:virtual:VIRTUAL_DumpView View: 0x490000 - 0x68ffff (valloc) 0027:trace:virtual:VIRTUAL_DumpView 0x490000 - 0x490fff c---- 0027:trace:virtual:VIRTUAL_DumpView 0x491000 - 0x68ffff c-rw- 0027:trace:seh:raise_exception code=c00000fd flags=0 addr=0x61006b93 ip=61006b93 tid=0027 0027:trace:seh:raise_exception eax=00491d90 ebx=0022063a ecx=00491000 edx=00000000 esi=0068feb0 edi=00000027 0027:trace:seh:raise_exception ebp=0068fdb8 esp=0068fd90 cs=0023 ds=002b es=002b fs=0063 gs=006b flags=00010287 0027:trace:seh:call_stack_handlers calling handler at 0x7bc98301 code=c00000fd flags=0 0027:Call KERNEL32.UnhandledExceptionFilter(0068f854) ret=7bc9833b wine: Unhandled stack overflow at address 0x61006b93 (thread 0027), starting debugger... --- snip ---
The corresponding source code to the crash is here: http://cygwin.com/cgi-bin/cvsweb.cgi/src/winsup/cygwin/dcrt0.cc?rev=1.445&am...
--- snip --- void *getstack (void *) __attribute__ ((noinline)); volatile char * getstack (volatile char * volatile p) { *p ^= 1; *p ^= 1; return p - 4096; }
/* extend the stack prior to fork longjmp */
void child_info_fork::alloc_stack () { volatile char * volatile stackp; #ifdef __x86_64__ __asm__ volatile ("movq %%rsp,%0": "=r" (stackp)); #else __asm__ volatile ("movl %%esp,%0": "=r" (stackp)); #endif /* Make sure not to try a hard allocation if we have been forked off from the main thread of a Cygwin process which has been started from a 64 bit parent. In that case the _tlsbase of the forked child is not the same as the _tlsbase of the parent (== stackbottom), but only because the stack of the parent has been slightly rearranged. See comment in wow64_revert_to_original_stack for details. We check here if the parent stack fits into the child stack. */ if (_tlsbase != stackbottom && (!wincap.is_wow64 () || stacktop < (char *) NtCurrentTeb ()->DeallocationStack || stackbottom > _tlsbase)) alloc_stack_hard_way (stackp); else { char *st = (char *) stacktop - 4096; while (_tlstop >= st) stackp = getstack (stackp); stackaddr = 0; /* This only affects forked children of a process started from a native 64 bit process, but it doesn't hurt to do it unconditionally. Fix StackBase in the child to be the same as in the parent, so that the computation of _my_tls is correct. */ _tlsbase = (PVOID) stackbottom; } }
...
/* Take over from libc's crt0.o and start the application. Note the various special cases when Cygwin DLL is being runtime loaded (as opposed to being link-time loaded by Cygwin apps) from a non cygwin app via LoadLibrary. */ void dll_crt0_1 (void *) { extern void initial_setlocale (); ... cygbench ("pre-forkee"); if (in_forkee) { /* If we've played with the stack, stacksize != 0. That means that fork() was invoked from other than the main thread. Make sure that frame pointer is referencing the new stack so that the OS knows what to do when it needs to increase the size of the stack.
NOTE: Don't do anything that involves the stack until you've completed this step. */ if (fork_info->stackaddr) { _tlsbase = (PVOID) fork_info->stackbottom; _tlstop = (PVOID) fork_info->stacktop; }
/* Not resetting _my_tls.incyg here because presumably fork will overwrite it with the value of the forker and all will be good. */ longjmp (fork_info->jmp, true); }
main_thread_sinit (); ... --- snip ---
The stack overflow happens in this code part in spawned "bash.exe" child process (forkee):
--- snip --- char *st = (char *) stacktop - 4096; while (_tlstop >= st) stackp = getstack (stackp); --- snip ---
Since the main thread stack is already committed there will be no further TIB StackLimit updates (guard page moved) which is what getstack() function (touch next stack page) implies. The expression "while (_tlstop >= st)" seems to be always true (equal).
$ wine --version wine-1.5.29-122-g865d53d
Regards