* exceptions.cc (stack_info::walk): Use method to find offset.

(handle_exceptions): Be more assertive in finding ebp for use under W2K.
Create a dummy stack frame for cases where program is dying and a stack dump is
being output.
(sig_handle): Fill out a GetThreadContext for use with a user-generated "core
dump".
This commit is contained in:
Christopher Faylor 2000-07-03 20:14:06 +00:00
parent 4bedf498d6
commit 8366e93be9
6 changed files with 68 additions and 37 deletions

View File

@ -1,3 +1,12 @@
Mon Jul 3 16:09:16 2000 Christopher Faylor <cgf@cygnus.com>
* exceptions.cc (stack_info::walk): Use method to find offset.
(handle_exceptions): Be more assertive in finding ebp for use under
W2K. Create a dummy stack frame for cases where program is dying and a
stack dump is being output.
(sig_handle): Fill out a GetThreadContext for use with a user-generated
"core dump".
Mon Jul 3 10:53:00 2000 Corinna Vinschen <corinna@vinschen.de> Mon Jul 3 10:53:00 2000 Corinna Vinschen <corinna@vinschen.de>
* include/cygwin/socket.h: Remove SOCK_PACKET define since it's * include/cygwin/socket.h: Remove SOCK_PACKET define since it's

View File

@ -637,9 +637,6 @@ dll_crt0_1 ()
(void) SetErrorMode (SEM_FAILCRITICALERRORS); (void) SetErrorMode (SEM_FAILCRITICALERRORS);
/* Initialize the heap. */
heap_init ();
/* Initialize events. */ /* Initialize events. */
events_init (); events_init ();
@ -673,6 +670,9 @@ dll_crt0_1 ()
longjmp (ciresrv->jmp, ciresrv->cygpid); longjmp (ciresrv->jmp, ciresrv->cygpid);
} }
/* Initialize the heap. */
heap_init ();
/* Initialize our process table entry. Don't use the parent info for /* Initialize our process table entry. Don't use the parent info for
dynamically loaded case. */ dynamically loaded case. */
pinfo_init ((dynamically_loaded) ? NULL : info); pinfo_init ((dynamically_loaded) ? NULL : info);

View File

@ -197,6 +197,7 @@ class stack_info
{ {
int first_time; /* True if just starting to iterate. */ int first_time; /* True if just starting to iterate. */
int walk (); /* Uses the "old" method */ int walk (); /* Uses the "old" method */
char *next_offset () {return *((char **) sf.AddrFrame.Offset);}
public: public:
STACKFRAME sf; /* For storing the stack information */ STACKFRAME sf; /* For storing the stack information */
void init (DWORD); /* Called the first time that stack info is needed */ void init (DWORD); /* Called the first time that stack info is needed */
@ -233,7 +234,7 @@ stack_info::walk ()
if (first_time) if (first_time)
/* Everything is filled out already */ /* Everything is filled out already */
ebp = (char **) sf.AddrFrame.Offset; ebp = (char **) sf.AddrFrame.Offset;
else if ((ebp = (char **) *(char **) sf.AddrFrame.Offset) != NULL) else if ((ebp = (char **) next_offset ()) != NULL)
{ {
sf.AddrFrame.Offset = (DWORD) ebp; sf.AddrFrame.Offset = (DWORD) ebp;
sf.AddrPC.Offset = sf.AddrReturn.Offset; sf.AddrPC.Offset = sf.AddrReturn.Offset;
@ -255,14 +256,14 @@ stack_info::walk ()
} }
/* Dump the stack */ /* Dump the stack */
void static void
stack (CONTEXT *cx) stack (CONTEXT *cx)
{ {
int i; int i;
thestack.init (cx->Ebp); /* Initialize from the input CONTEXT */ thestack.init (cx->Ebp); /* Initialize from the input CONTEXT */
small_printf ("Stack trace:\r\nFrame Function Args\r\n"); small_printf ("Stack trace:\r\nFrame Function Args\r\n");
for (i = 0; i < 16 && thestack++ ; i++) for (i = 0; i < 16 && thestack++; i++)
{ {
small_printf ("%08x %08x ", thestack.sf.AddrFrame.Offset, small_printf ("%08x %08x ", thestack.sf.AddrFrame.Offset,
thestack.sf.AddrPC.Offset); thestack.sf.AddrPC.Offset);
@ -281,7 +282,7 @@ cygwin_stackdump()
CONTEXT c; CONTEXT c;
c.ContextFlags = CONTEXT_FULL; c.ContextFlags = CONTEXT_FULL;
GetThreadContext (GetCurrentThread (), &c); GetThreadContext (GetCurrentThread (), &c);
stack(&c); stack (&c);
} }
static int NO_COPY keep_looping = 0; static int NO_COPY keep_looping = 0;
@ -342,7 +343,7 @@ try_to_debug ()
return 0; return 0;
} }
void static void
stackdump (EXCEPTION_RECORD *e, CONTEXT *in) stackdump (EXCEPTION_RECORD *e, CONTEXT *in)
{ {
char *p; char *p;
@ -441,6 +442,17 @@ handle_exceptions (EXCEPTION_RECORD *e, void *, CONTEXT *in, void *)
if (myself->getsig(sig).sa_mask & SIGTOMASK (sig)) if (myself->getsig(sig).sa_mask & SIGTOMASK (sig))
syscall_printf ("signal %d, masked %p", sig, myself->getsig(sig).sa_mask); syscall_printf ("signal %d, masked %p", sig, myself->getsig(sig).sa_mask);
debug_printf ("In cygwin_except_handler calling %p",
myself->getsig(sig).sa_handler);
DWORD *ebp = (DWORD *)in->Esp;
for (DWORD *bpend = (DWORD *) __builtin_frame_address (0); ebp > bpend; ebp--)
if (*ebp == in->SegCs && ebp[-1] == in->Eip)
{
ebp -= 2;
break;
}
if (!myself->progname[0] if (!myself->progname[0]
|| (void *) myself->getsig(sig).sa_handler == (void *) SIG_DFL || (void *) myself->getsig(sig).sa_handler == (void *) SIG_DFL
|| (void *) myself->getsig(sig).sa_handler == (void *) SIG_IGN || (void *) myself->getsig(sig).sa_handler == (void *) SIG_IGN
@ -467,26 +479,18 @@ handle_exceptions (EXCEPTION_RECORD *e, void *, CONTEXT *in, void *)
system_printf ("Error while dumping state (probably corrupted stack)"); system_printf ("Error while dumping state (probably corrupted stack)");
else else
{ {
HANDLE hthread; CONTEXT c = *in;
DuplicateHandle (hMainProc, GetCurrentThread (), DWORD stack[6];
hMainProc, &hthread, 0, FALSE, DUPLICATE_SAME_ACCESS); stack[0] = in->Ebp;
stackdump (e, in); stack[1] = in->Eip;
stack[2] = stack[3] = stack[4] = stack[5] = 0;
c.Ebp = (DWORD) &stack;
stackdump (e, &c);
} }
try_to_debug (); try_to_debug ();
really_exit (EXIT_SIGNAL | sig); really_exit (EXIT_SIGNAL | sig);
} }
debug_printf ("In cygwin_except_handler calling %p",
myself->getsig(sig).sa_handler);
DWORD *ebp = (DWORD *)in->Esp;
for (DWORD *bpend = ebp - 16; ebp > bpend; ebp--)
if (*ebp == in->SegCs && ebp[-1] == in->Eip)
{
ebp -= 2;
break;
}
sig_send (NULL, sig, (DWORD) ebp); // Signal myself sig_send (NULL, sig, (DWORD) ebp); // Signal myself
return 0; return 0;
} }
@ -954,8 +958,12 @@ done:
exit_sig: exit_sig:
if (sig == SIGQUIT || sig == SIGABRT) if (sig == SIGQUIT || sig == SIGABRT)
{ {
stackdump (NULL, NULL); CONTEXT c;
c.ContextFlags = CONTEXT_FULL;
GetThreadContext (hMainThread, &c);
stackdump (NULL, &c);
try_to_debug (); try_to_debug ();
really_exit (EXIT_SIGNAL | sig);
} }
sigproc_printf ("signal %d, about to call do_exit", sig); sigproc_printf ("signal %d, about to call do_exit", sig);
TerminateThread (hMainThread, 0); TerminateThread (hMainThread, 0);

View File

@ -445,13 +445,13 @@ fork ()
MALLOC_CHECK; MALLOC_CHECK;
rc = fork_copy (pi, "dll data", dll_data_start, dll_data_end,
dll_bss_start, dll_bss_end, NULL);
rc = fork_copy (pi, "user/cygwin data", rc = fork_copy (pi, "user/cygwin data",
user_data->data_start, user_data->data_end, user_data->data_start, user_data->data_end,
user_data->bss_start, user_data->bss_end, user_data->bss_start, user_data->bss_end,
ch.heapbase, ch.heapptr,
stack_here, ch.stackbottom, stack_here, ch.stackbottom,
dll_data_start, dll_data_end, NULL);
dll_bss_start, dll_bss_end, NULL);
MALLOC_CHECK; MALLOC_CHECK;
if (!rc) if (!rc)
@ -526,14 +526,22 @@ fork ()
} }
sync_with_parent ("after longjmp.", TRUE); sync_with_parent ("after longjmp.", TRUE);
ProtectHandle (hParent);
#ifdef DEBUGGING #ifdef DEBUGGING
char c; char c;
if (GetEnvironmentVariable ("FORKDEBUG", &c, 1)) if (GetEnvironmentVariable ("FORKDEBUG", &c, 1))
try_to_debug (); try_to_debug ();
char buf[80];
if (GetEnvironmentVariable ("CYGWIN_FORK_SLEEP", buf, sizeof (buf)))
{
small_printf ("Sleeping %d after fork, pid %u\n", atoi (buf), GetCurrentProcessId ());
Sleep (atoi(buf));
}
#endif #endif
heap_init ();
ProtectHandle (hParent);
/* If we've played with the stack, stacksize != 0. That means that /* If we've played with the stack, stacksize != 0. That means that
fork() was invoked from other than the main thread. Make sure that fork() was invoked from other than the main thread. Make sure that
when the "main" thread exits it calls do_exit, like a normal process. when the "main" thread exits it calls do_exit, like a normal process.

View File

@ -20,6 +20,8 @@ details. */
static unsigned page_const = 0; static unsigned page_const = 0;
HANDLE cygwin_heap;
static __inline__ int static __inline__ int
getpagesize(void) getpagesize(void)
{ {
@ -36,9 +38,9 @@ heap_init ()
/* If we're the forkee, we must allocate the heap at exactly the same place /* If we're the forkee, we must allocate the heap at exactly the same place
as our parent. If not, we don't care where it ends up. */ as our parent. If not, we don't care where it ends up. */
page_const = getpagesize();
if (brkbase) if (brkbase)
{ {
DWORD chunk = brkchunk; /* allocation chunk */ DWORD chunk = brkchunk; /* allocation chunk */
/* total size commited in parent */ /* total size commited in parent */
DWORD allocsize = (char *) brktop - (char *) brkbase; DWORD allocsize = (char *) brktop - (char *) brkbase;
@ -46,14 +48,13 @@ heap_init ()
DWORD reserve_size = chunk * ((allocsize + (chunk - 1)) / chunk); DWORD reserve_size = chunk * ((allocsize + (chunk - 1)) / chunk);
/* Loop until we've managed to reserve an adequate amount of memory. */ /* Loop until we've managed to reserve an adequate amount of memory. */
char *p; void *p;
for (;;) for (;;)
{ {
p = (char *) VirtualAlloc (brkbase, reserve_size, p = MapViewOfFileEx (cygwin_heap, FILE_MAP_COPY, 0L, 0L, 0L, brkbase);
MEM_RESERVE, PAGE_READWRITE);
if (p) if (p)
break; break;
if ((reserve_size -= page_const) <= allocsize) if ((reserve_size -= (page_const + 1)) <= allocsize)
break; break;
} }
if (p == NULL) if (p == NULL)
@ -61,20 +62,25 @@ heap_init ()
brkchunk, myself->pid); brkchunk, myself->pid);
if (p != brkbase) if (p != brkbase)
api_fatal ("heap allocated but not at %p", brkbase); api_fatal ("heap allocated but not at %p", brkbase);
if (! VirtualAlloc (brkbase, allocsize, MEM_COMMIT, PAGE_READWRITE)) if (!VirtualAlloc (brkbase, allocsize, MEM_COMMIT, PAGE_READWRITE))
api_fatal ("MEM_COMMIT failed, %E"); api_fatal ("MEM_COMMIT failed, %E");
} }
else else
{ {
page_const = getpagesize() - 1;
/* Initialize page mask and default heap size. Preallocate a heap /* Initialize page mask and default heap size. Preallocate a heap
* to assure contiguous memory. */ * to assure contiguous memory. */
brk = brktop = brkbase = VirtualAlloc(NULL, brkchunk, MEM_RESERVE, PAGE_NOACCESS); cygwin_heap = CreateFileMapping ((HANDLE) 0xffffffff, &sec_all, PAGE_WRITECOPY | SEC_RESERVE, 0L, brkchunk, NULL);
if (cygwin_heap == NULL)
api_fatal ("2. unable to allocate shared memory for heap, heap_chunk_size %d, %E", brkchunk);
brk = brktop = brkbase = MapViewOfFile (cygwin_heap, 0, 0L, 0L, 0);
// brk = brktop = brkbase = VirtualAlloc(NULL, brkchunk, MEM_RESERVE, PAGE_NOACCESS);
if (brkbase == NULL) if (brkbase == NULL)
api_fatal ("2. unable to allocate heap, heap_chunk_size %d, %E", api_fatal ("2. unable to allocate heap, heap_chunk_size %d, %E",
brkchunk); brkchunk);
} }
page_const--;
malloc_init (); malloc_init ();
} }

View File

@ -172,7 +172,7 @@ pinfo *__stdcall procinfo (int n);
enum enum
{ {
PROC_MAGIC = 0xaf08f000, PROC_MAGIC = 0xaf09f000,
PROC_FORK = PROC_MAGIC + 1, PROC_FORK = PROC_MAGIC + 1,
PROC_EXEC = PROC_MAGIC + 2, PROC_EXEC = PROC_MAGIC + 2,
PROC_SPAWN = PROC_MAGIC + 3, PROC_SPAWN = PROC_MAGIC + 3,