delorie.com/archives/browse.cgi   search  
Mail Archives: cygwin/2015/07/06/06:02:25

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: <cygwin.cygwin.com>
List-Subscribe: <mailto:cygwin-subscribe AT cygwin DOT com>
List-Archive: <http://sourceware.org/ml/cygwin/>
List-Post: <mailto:cygwin AT cygwin DOT com>
List-Help: <mailto:cygwin-help AT cygwin DOT com>, <http://sourceware.org/ml/#faqs>
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 <corinna-cygwin AT cygwin DOT com>
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: <announce DOT 20150705213417 DOT GH2918 AT calimero DOT vinschen DOT de> <5599E4C5 DOT 1010109 AT cornell DOT edu>
MIME-Version: 1.0
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 <error: Cannot access memory at address 0x40ac3>
  (gdb) p addr
  $2 =3D 0x43848 <error: Cannot access memory at address 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 <error: Cannot access memory at address 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 <windows.h>

  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 <alloca.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <setjmp.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <sys/wait.h>
#include <sys/fcntl.h>
#include <windows.h>

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--

- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019