X-Recipient: archive-cygwin AT delorie DOT com DomainKey-Signature: a=rsa-sha1; c=nofws; d=sourceware.org; h=list-id :list-unsubscribe:list-subscribe:list-archive:list-post :list-help:sender:date:from:to:subject:message-id:reply-to :references:mime-version:content-type:in-reply-to; q=dns; s= default; b=rTcOEEPseI+o1iguZPcKGwMn/m/HlWuf8Y8hnPfwLw3zT4MWPhhcl btWlz1GdGCdC1w8SfceQfu0Ape4XiWIZ1jNv8kxbg5s6sI6c5/T8jqvfG+5NxbZw dcvzNNx0SxK7A3iNRCoDyfGl98I+kGi2n7iyDJP65oJ4mlPNggSeZc= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=sourceware.org; h=list-id :list-unsubscribe:list-subscribe:list-archive:list-post :list-help:sender:date:from:to:subject:message-id:reply-to :references:mime-version:content-type:in-reply-to; s=default; bh=v4ShDL6jv26fj78dcfgH4wqbOiY=; b=Am7/LlMPRsJV0H4BGIQQBNpR7S28 GvOVTptQz3hJbLCKFklNEFQoDofNOfa/DNMYLFaGf4JxfQHZ2xwvarv7nbZPjnVY dToB9OePRlhMaGJ+nBMeGwSnqOjf8fjHUP1ao+NpK84/ARY2MiWKBiwlimVJscyA 4UznUdPqL1ldbew= Mailing-List: contact cygwin-help AT cygwin DOT com; run by ezmlm List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: cygwin-owner AT cygwin DOT com Mail-Followup-To: cygwin AT cygwin DOT com Delivered-To: mailing list cygwin AT cygwin DOT com Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-4.1 required=5.0 tests=AWL,BAYES_50,KAM_LAZY_DOMAIN_SECURITY autolearn=no version=3.3.2 X-HELO: calimero.vinschen.de Date: Mon, 6 Jul 2015 12:01:58 +0200 From: Corinna Vinschen To: cygwin AT cygwin DOT com Subject: Re: [ANNOUNCEMENT] TEST RELEASE: Cygwin 2.1.0-0.4 Message-ID: <20150706100158.GJ2918@calimero.vinschen.de> Reply-To: cygwin AT cygwin DOT com Mail-Followup-To: cygwin AT cygwin DOT com References: <5599E4C5 DOT 1010109 AT cornell DOT edu> MIME-Version: 1.0 Content-Type: multipart/signed; micalg=pgp-sha256; protocol="application/pgp-signature"; boundary="QHp3Wr1K3N9pKO2V" Content-Disposition: inline In-Reply-To: <5599E4C5.1010109@cornell.edu> User-Agent: Mutt/1.5.23 (2014-03-12) --QHp3Wr1K3N9pKO2V Content-Type: multipart/mixed; boundary="Wt10+cXOThorkX0z" Content-Disposition: inline --Wt10+cXOThorkX0z Content-Type: text/plain; charset=utf-8 Content-Disposition: inline Content-Transfer-Encoding: quoted-printable Hi Ken, thanks for further testing this. On Jul 5 22:15, Ken Brown wrote: > On 7/5/2015 5:34 PM, Corinna Vinschen wrote: > >This test release needs some good testing! >=20 > I repeated the emacs experiment discussed in the "[ANNOUNCEMENT] TEST > RELEASE: Cygwin 2.1.0-0.1" thread. In the 32-bit case, the results were > more-or-less the same as before: I forced a stack overflow, emacs recover= ed, > I tried to continue working, there was a second SIGSEGV, and handle_sigse= gv > bailed out because garbage collection was in progress. This time I was > unable to prevent the second SIGSEGV by resetting max-specpdl-size and > max-lisp-eval-depth. I'm not sure what caused the second SIGSEGV, but it > might have nothing to do with Cygwin. >=20 > In the 64-bit case, however, the recovery from stack overflow never happe= ned > (i.e., the program never reached the siglongjmp). Here's a gdb session: > [...] > 1647 if (!getrlimit (RLIMIT_STACK, &rlim)) > (gdb) > 1656 beg =3D stack_bottom; > (gdb) > 1657 end =3D stack_bottom + stack_direction * rlim.rlim_cur; > (gdb) > 1658 if (beg > end) > (gdb) > 1660 addr =3D (char *) siginfo->si_addr; > (gdb) > 1663 if (beg < addr && addr < end > (gdb) p beg > $1 =3D 0x82ca27 "" > (gdb) p addr > $2 =3D 0x33ff8 "" I can't reproduce this. It works fine for me. For reference I attached my simplified testcase again. It's basically the emacs SIGSEGV setup, main triggers the stack overflow, the handler tries to write a file for testing if that works from the handler, then it siglongjmps. The main function tests if it can still fork, and then it repeats the action to test if we're back to normal in terms of signal handling. If it works (and it does for me) the output looks like this: $ ./sigalt command loop 1 before crash command loop 1 after crash In child In parent command loop 2 before crash command loop 2 after crash In child In parent On W8.1 for a standard GCC build of this testcase I get: (gdb) p beg $1 =3D 0x40ac3 (gdb) p addr $2 =3D 0x43848 (gdb) p end $3 =3D 0x23cac3 "" (gdb) p/x rlim.rlim_cur $5 =3D 0x1fc000 Check default stacksize: )$ peflags -x ./sigalt ./sigalt: stack reserve size : 2097152 (0x200000) bytes 0x200000 - dead zone 4K - default W8.1 64 bit guardpagesize 3 * 4K =3D=3D 0x1fc000, the value rlim.rlim_cur returns. Looks good to me. On W8.1 32 bit under WOW: (gdb) p beg $1 =3D 0x8fc33 "" (gdb) p addr $2 =3D 0x92d5c (gdb) p end $3 =3D 0x28cc33 "" (gdb) p/x rlim.rlim_cur $4 =3D 0x1fd000 $ peflags -x ./sigalt ./sigalt: stack reserve size : 2097152 (0x200000) bytes 0x200000 - dead zone 4K - default W8.1 32 bit guardpagesize 2 * 4K =3D=3D 0x1fd000. On W7 32 bit native: (gdb) p beg $1 =3D 0x2ec43 "\376\356..." (gdb) p addr $2 =3D 0x32d6c "" (gdb) p end $3 =3D 0x22cc43 "" (gdb) p rlim.rlim_cur $4 =3D 2088960 (gdb) p/x rlim.rlim_cur $5 =3D 0x1fe000 $ peflags -x ./sigalt ./sigalt: stack reserve size : 2097152 (0x200000) bytes 0x200000 - dead zone 4K - default W7 32 bit guardpagesize 1 * 4K =3D=3D 0x1fe000. > Note that addr < beg, so we never reach the siglongjmp. I have no explanation for this. What OS? What does rlim_cur contain? What does peflags -x print for this executable? And last but not least, what is emacs doing there? The stack should be pretty much in a good shape when it's back to the main loop. The stack is fully commited and has the default number of guardpages at the bottom, as it is just short of the stack overflow. For debugging purposes I also added a global variable called "tib" and a memory info struct called "m" to the testcase which are initialized right at the start of main. tib points to the start of the TEB (Thread Environment Block, a Windows per-thread bookkeeping structure) of the main thread. If you expand it right after it's fetched, you get something along these lines: (gdb) p *tib $2 =3D {ExceptionList =3D 0x22cd78, StackBase =3D 0x230000, StackLimit = =3D 0x20c000, SubSystemTib =3D 0x0, {FiberData =3D 0x1e00, Version =3D 7680}, ArbitraryUserPointer =3D 0x0, Self =3D 0x7ffdf000} Note the values of StackBase and StackLimit and compare with your beg and end values. StackBase is the upper limit of the stack. It grows downward from there. StackLimit is the lowest address as yet commited. It's not mu= ch yet as you can see, 0x230000-0x20c000 =3D=3D 0x24000 =3D=3D 144K. Since Cy= gwin executables have a default stack of 2 Megs, the allocation base of the stack is probably at 0x30000. This can be checked by looking at m: (gdb) p m $1 =3D {BaseAddress =3D 0x22c000, AllocationBase =3D 0x30000, AllocationP= rotect =3D 4, RegionSize =3D 16384, State =3D 4096, Protect =3D 4, Type =3D 131072} See the value of AllocationBase. When you hit the breakpoint in handle_sigsegv, the output of tib should look like this: (gdb) p *tib $2 =3D {ExceptionList =3D 0x22cd78, StackBase =3D 0x230000, StackLimit = =3D 0x32000, SubSystemTib =3D 0x0, {FiberData =3D 0x1e00, Version =3D 7680}, ArbitraryUserPointer =3D 0x0, Self =3D 0x7ffdf000} Observe the value of StackLimit. For this output I ran the testcase on W7 32 bit. It has a default guardpage of 4K. The new wrapper I wrote in Cygwin restored the stack to its state rifght before the stack overflow occured: - At 0x30000 we have the 4K dead zone, which is always only reserved, never commited. - At 0x31000 the 4K guard page starts. - Thus the StackLimit (the start of the commited region of the stack) starts at 0x32000. You can utilize tib and m for testing in emacs as well. Just do this: #include NT_TIB *tib; MEMORY_BASIC_INFORMATION m; [...] in main: /* Record (approximately) where the stack begins. */ stack_bottom =3D &stack_bottom_variable; tib =3D (NT_TIB *) __readfsdword(PcTeb); VirtualQuery (stack_bottom, &m, sizeof m); It would be nice to find out why this happens to your emacs... Thanks, Corinna --=20 Corinna Vinschen Please, send mails regarding Cygwin to Cygwin Maintainer cygwin AT cygwin DOT com Red Hat --Wt10+cXOThorkX0z Content-Type: text/plain; charset=utf-8 Content-Disposition: attachment; filename="sigalt.c" #include #include #include #include #include #include #include #include #include #include #include int stack_direction; char *stack_bottom; sigjmp_buf return_to_command_loop; NT_TIB *tib; MEMORY_BASIC_INFORMATION m; /* Attempt to recover from SIGSEGV caused by C stack overflow. */ static void handle_sigsegv (int sig, siginfo_t *siginfo, void *arg) { struct rlimit rlim; int fp = open ("sigalt.out", O_CREAT | O_TRUNC | O_WRONLY, 0644); if (fp < 0) perror ("open"); else { write (fp, "ping\n", 5); close (fp); } if (!getrlimit (RLIMIT_STACK, &rlim)) { enum { STACK_DANGER_ZONE = 32 * 1024 }; char *beg, *end, *addr; beg = stack_bottom; end = stack_bottom + stack_direction * rlim.rlim_cur; if (beg > end) addr = beg, beg = end, end = addr; addr = (char *) siginfo->si_addr; /* If we're somewhere on stack and too close to one of its boundaries, most likely this is it. */ if (beg < addr && addr < end && (addr - beg < STACK_DANGER_ZONE || end - addr < STACK_DANGER_ZONE)) siglongjmp (return_to_command_loop, 1); } /* Otherwise we can't do anything with this. */ //abort (); } static int init_sigsegv (void) { struct sigaction sa; stack_t ss; stack_direction = ((char *) &ss < stack_bottom) ? -1 : 1; ss.ss_sp = malloc (SIGSTKSZ); ss.ss_size = SIGSTKSZ; ss.ss_flags = 0; if (sigaltstack (&ss, NULL) < 0) return 0; sigfillset (&sa.sa_mask); sa.sa_sigaction = handle_sigsegv; sa.sa_flags = SA_SIGINFO | SA_ONSTACK; return sigaction (SIGSEGV, &sa, NULL) < 0 ? 0 : 1; } void foo () { int buf[512]; foo (); } int main () { int status; char stack_bottom_variable; /* Record (approximately) where the stack begins. */ stack_bottom = &stack_bottom_variable; tib = (NT_TIB *) __readfsdword(PcTeb); VirtualQuery (stack_bottom, &m, sizeof m); init_sigsegv (); if (!sigsetjmp (return_to_command_loop, 1)) { printf ("command loop 1 before crash\n"); foo (); } else { printf ("command loop 1 after crash\n"); switch (fork ()) { case -1: perror ("fork"); break; case 0: printf ("In child\n"); exit (0); default: wait (&status); printf ("In parent\n"); break; } } if (!sigsetjmp (return_to_command_loop, 1)) { printf ("command loop 2 before crash\n"); foo (); } else { printf ("command loop 2 after crash\n"); switch (fork ()) { case -1: perror ("fork"); break; case 0: printf ("In child\n"); exit (0); default: wait (&status); printf ("In parent\n"); break; } } return 0; } --Wt10+cXOThorkX0z-- --QHp3Wr1K3N9pKO2V Content-Type: application/pgp-signature -----BEGIN PGP SIGNATURE----- Version: GnuPG v2 iQIcBAEBCAAGBQJVmlIWAAoJEPU2Bp2uRE+gRu0P/i3fiMI3bwgfJUu8xK2e133h 9tjLdIUsQl51oWPW8KcN8e6ZXS2ShTQOud9lAd8U7NPkVOoVa2DzrnRz+dGYu1R+ g4z7tY6S0oyUYdYhgK/UJIa+DzpS43GoIglbQXpfpmTNhSosxJZVj5BWZoLXOoEP ZzrECJ/vK0/1ZuDxJ5/y2xpvIqkpVEMRDlfRgOYTf2M+5T5EoDl+tp98gyqa6zsj Mnynt/qZuE/corh1gkFZuDnCTFGaInJKKRa5R54DITiWB7Kt9vTnSkkhRWxy2Bus 7vQyexwOccmBMpaNBNC3/lURoRpaDglJ+vy0YE6dIBoxTXMOqjQa9wQmauxeG94O Hp7EU5zIplkBCkiKSrnbbnLNh/uOk1dAUp/pdam7zTpZ/H+vf3unsY/PCwujXFoy hYHxy0TUOZVrY2CiR1jOkIyB7rdYiLaXLp6eCnZ4+X1Y9ByirfaAAToq7LMunyJb oQADZrbwGtyWcspY/eX6gw8K40/Op2OlDYhKzJqxqLJ3OxY7tBC1xQD9OJ3wTajI 95Zx/DtvZ88AePVbItp7gQhaaoT9Ya10VOsMcbELXVz5GzVtA/Yd1FtesXBG2BK3 580e/eVh/uoFtouIr/J6U1tXP+urpjWnJr2c2FKQWcBQAamc30xvrFoO1hDJPChv 1L7sGt/H3+wfsN5Kyotn =1cty -----END PGP SIGNATURE----- --QHp3Wr1K3N9pKO2V--