* exceptions.cc (INIT_EXCEPTION_HANDLER): Eliminate.

(init_exceptions): Just use init_exception_handler.
(open_stackdumpfile): New function.
(stack_info::first_time): Eliminate.
(stack_info::init): Set up fields to avoid "first_time" consideration.
(stack_info::walk): Remove "first_time" consideration.
(stackdump): Change arguments to accept initial frame pointer and open stack
file flag.
(stack): Eliminate.
(cygwin_stackdump): Use stackdump() rather than stack().
(try_to_debug): Remove all synchronization logic.  Just keep looping in
exception handler until debugger notices us.  Return 1 if successfully started
debugger.
(handle_exceptions): Just return if we know that we're debugging.  Reorganize
to avoid creating a stackdump file if we are starting a debugger.  Return from
exception handler if debugger started successfully.
(sig_handle): Create a stackdump only if debugger wasn't started.
* winsup.h (try_to_debug): Add an argument.
This commit is contained in:
Christopher Faylor 2001-04-30 03:09:19 +00:00
parent 2b5803d4b7
commit 8abeff1ead
3 changed files with 100 additions and 94 deletions

View File

@ -1,3 +1,25 @@
Sun Apr 29 22:28:06 2001 Christopher Faylor <cgf@cygnus.com>
* exceptions.cc (INIT_EXCEPTION_HANDLER): Eliminate.
(init_exceptions): Just use init_exception_handler.
(open_stackdumpfile): New function.
(stack_info::first_time): Eliminate.
(stack_info::init): Set up fields to avoid "first_time" consideration.
(stack_info::walk): Remove "first_time" consideration.
(stackdump): Change arguments to accept initial frame pointer and open
stack file flag.
(stack): Eliminate.
(cygwin_stackdump): Use stackdump() rather than stack().
(try_to_debug): Remove all synchronization logic. Just keep looping in
exception handler until debugger notices us. Return 1 if successfully
started debugger.
(handle_exceptions): Just return if we know that we're debugging.
Reorganize to avoid creating a stackdump file if we are starting a
debugger. Return from exception handler if debugger started
successfully.
(sig_handle): Create a stackdump only if debugger wasn't started.
* winsup.h (try_to_debug): Add an argument.
Sun Apr 29 21:41:25 2001 Christopher Faylor <cgf@cygnus.com> Sun Apr 29 21:41:25 2001 Christopher Faylor <cgf@cygnus.com>
* path.cc (symlink_info::check): Remove extra arguments, move * path.cc (symlink_info::check): Remove extra arguments, move

View File

@ -109,8 +109,6 @@ init_exception_handler (exception_list *el)
el->prev = _except_list; el->prev = _except_list;
_except_list = el; _except_list = el;
} }
#define INIT_EXCEPTION_HANDLER(el) init_exception_handler (el)
#endif #endif
void void
@ -134,9 +132,7 @@ set_console_handler ()
extern "C" void extern "C" void
init_exceptions (exception_list *el) init_exceptions (exception_list *el)
{ {
#ifdef INIT_EXCEPTION_HANDLER init_exception_handler (el);
INIT_EXCEPTION_HANDLER (el);
#endif
} }
extern "C" void extern "C" void
@ -155,6 +151,29 @@ error_start_init (const char *buf)
__small_sprintf (debugger_command, "%s %s", buf, myself_posix_name); __small_sprintf (debugger_command, "%s %s", buf, myself_posix_name);
} }
static void
open_stackdumpfile ()
{
if (myself->progname[0])
{
const char *p;
/* write to progname.stackdump if possible */
if ((p = strrchr (myself->progname, '\\')))
p++;
else
p = myself->progname;
char corefile[strlen (p) + sizeof (".stackdump")];
__small_sprintf (corefile, "%s.stackdump", p);
HANDLE h = CreateFile (corefile, GENERIC_WRITE, 0, &sec_none_nih,
CREATE_ALWAYS, 0, 0);
if (h != INVALID_HANDLE_VALUE)
{
system_printf ("Dumping stack trace to %s", corefile);
SetStdHandle (STD_ERROR_HANDLE, h);
}
}
}
/* Utilities for dumping the stack, etc. */ /* Utilities for dumping the stack, etc. */
static void static void
@ -201,13 +220,11 @@ exception (EXCEPTION_RECORD *e, CONTEXT *in)
/* A class for manipulating the stack. */ /* A class for manipulating the stack. */
class stack_info class stack_info
{ {
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);} 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 */
stack_info (): first_time (1) {}
/* Postfix ++ iterates over the stack, returning zero when nothing is left. */ /* Postfix ++ iterates over the stack, returning zero when nothing is left. */
int operator ++(int) { return this->walk (); } int operator ++(int) { return this->walk (); }
@ -224,11 +241,12 @@ static signal_dispatch sigsave;
void void
stack_info::init (DWORD ebp) stack_info::init (DWORD ebp)
{ {
first_time = 1; # define debp ((DWORD *) ebp)
memset (&sf, 0, sizeof (sf)); memset (&sf, 0, sizeof (sf));
sf.AddrFrame.Offset = ebp; sf.AddrFrame.Offset = ebp;
sf.AddrPC.Offset = ((DWORD *) ebp)[1]; sf.AddrReturn.Offset = debp[1];
sf.AddrFrame.Mode = AddrModeFlat; sf.AddrFrame.Mode = AddrModeFlat;
# undef debp
} }
/* Walk the stack by looking at successive stored 'bp' frames. /* Walk the stack by looking at successive stored 'bp' frames.
@ -237,10 +255,7 @@ int
stack_info::walk () stack_info::walk ()
{ {
char **ebp; char **ebp;
if (first_time) if ((ebp = (char **) next_offset ()) != NULL)
/* Everything is filled out already */
ebp = (char **) sf.AddrFrame.Offset;
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;
@ -248,7 +263,6 @@ stack_info::walk ()
else else
return 0; return 0;
first_time = 0;
if (!sf.AddrPC.Offset) if (!sf.AddrPC.Offset)
return 0; /* stack frames are exhausted */ return 0; /* stack frames are exhausted */
@ -261,13 +275,20 @@ stack_info::walk ()
return 1; return 1;
} }
/* Dump the stack */
static void static void
stack (CONTEXT *cx) stackdump (DWORD ebp, int open_file)
{ {
extern unsigned long rlim_core;
if (rlim_core == 0UL)
return;
if (open_file)
open_stackdumpfile ();
int i; int i;
thestack.init (cx->Ebp); /* Initialize from the input CONTEXT */ thestack.init (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++)
{ {
@ -288,15 +309,13 @@ cygwin_stackdump ()
CONTEXT c; CONTEXT c;
c.ContextFlags = CONTEXT_FULL; c.ContextFlags = CONTEXT_FULL;
GetThreadContext (GetCurrentThread (), &c); GetThreadContext (GetCurrentThread (), &c);
stack (&c); stackdump (c.Ebp, 0);
} }
static int NO_COPY keep_looping = 0;
#define TIME_TO_WAIT_FOR_DEBUGGER 10000 #define TIME_TO_WAIT_FOR_DEBUGGER 10000
extern "C" int extern "C" int
try_to_debug () try_to_debug (bool waitloop)
{ {
debug_printf ("debugger_command '%s'", debugger_command); debug_printf ("debugger_command '%s'", debugger_command);
if (*debugger_command == '\0') if (*debugger_command == '\0')
@ -306,6 +325,7 @@ try_to_debug ()
BOOL dbg; BOOL dbg;
SetThreadPriority (hMainThread, THREAD_PRIORITY_HIGHEST);
PROCESS_INFORMATION pi = {NULL, 0, 0, 0}; PROCESS_INFORMATION pi = {NULL, 0, 0, 0};
STARTUPINFO si = {0, NULL, NULL, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL}; STARTUPINFO si = {0, NULL, NULL, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL};
@ -348,73 +368,37 @@ try_to_debug ()
NULL, NULL,
&si, &si,
&pi); &pi);
if (!dbg)
static int NO_COPY keep_looping = 0;
if (dbg)
{ {
system_printf ("Failed to start debugger: %E"); if (!waitloop)
/* FIXME: need to know handles of all running threads to return 1;
resume_all_threads_except (current_thread_id); SetThreadPriority (hMainThread, THREAD_PRIORITY_IDLE);
*/
}
else
{
char event_name [sizeof ("cygwin_error_start_event") + 9];
DWORD win32_pid = GetCurrentProcessId ();
__small_sprintf (event_name, "cygwin_error_start_event%x", win32_pid);
HANDLE sync_with_dbg = CreateEvent (NULL, TRUE, FALSE, event_name);
keep_looping = 1;
while (keep_looping) while (keep_looping)
{ /* spin */;
if (sync_with_dbg == NULL)
Sleep (TIME_TO_WAIT_FOR_DEBUGGER);
else
{
if (WaitForSingleObject (sync_with_dbg,
TIME_TO_WAIT_FOR_DEBUGGER) == WAIT_OBJECT_0)
break;
}
}
} }
system_printf ("Failed to start debugger: %E");
/* FIXME: need to know handles of all running threads to
resume_all_threads_except (current_thread_id);
*/
return 0; return 0;
} }
static void
stackdump (EXCEPTION_RECORD *e, CONTEXT *in)
{
extern unsigned long rlim_core;
const char *p;
if (rlim_core == 0UL)
return;
if (myself->progname[0])
{
/* write to progname.stackdump if possible */
if ((p = strrchr (myself->progname, '\\')))
p++;
else
p = myself->progname;
char corefile[strlen (p) + sizeof (".stackdump")];
__small_sprintf (corefile, "%s.stackdump", p);
HANDLE h = CreateFile (corefile, GENERIC_WRITE, 0, &sec_none_nih,
CREATE_ALWAYS, 0, 0);
if (h != INVALID_HANDLE_VALUE)
{
system_printf ("Dumping stack trace to %s", corefile);
SetStdHandle (STD_ERROR_HANDLE, h);
}
}
if (e)
exception (e, in);
stack (in);
}
/* Main exception handler. */ /* Main exception handler. */
static int static int
handle_exceptions (EXCEPTION_RECORD *e, void *, CONTEXT *in, void *) handle_exceptions (EXCEPTION_RECORD *e, void *, CONTEXT *in, void *)
{ {
int sig; int sig;
static int NO_COPY debugging = 0;
static int NO_COPY recursed = 0;
if (debugging)
return 0;
/* If we've already exited, don't do anything here. Returning 1 /* If we've already exited, don't do anything here. Returning 1
tells Windows to keep looking for an exception handler. */ tells Windows to keep looking for an exception handler. */
@ -499,8 +483,6 @@ handle_exceptions (EXCEPTION_RECORD *e, void *, CONTEXT *in, void *)
|| (void *) myself->getsig (sig).sa_handler == (void *) SIG_IGN || (void *) myself->getsig (sig).sa_handler == (void *) SIG_IGN
|| (void *) myself->getsig (sig).sa_handler == (void *) SIG_ERR) || (void *) myself->getsig (sig).sa_handler == (void *) SIG_ERR)
{ {
static NO_COPY int traced = 0;
/* Print the exception to the console */ /* Print the exception to the console */
if (e) if (e)
{ {
@ -516,20 +498,22 @@ handle_exceptions (EXCEPTION_RECORD *e, void *, CONTEXT *in, void *)
/* Another exception could happen while tracing or while exiting. /* Another exception could happen while tracing or while exiting.
Only do this once. */ Only do this once. */
if (traced++) if (recursed++)
system_printf ("Error while dumping state (probably corrupted stack)"); system_printf ("Error while dumping state (probably corrupted stack)");
else else
{ {
CONTEXT c = *in; if (try_to_debug (0))
DWORD stack[6]; {
stack[0] = in->Ebp; debugging = 1;
stack[1] = in->Eip; return 0;
stack[2] = stack[3] = stack[4] = stack[5] = 0; }
c.Ebp = (DWORD) &stack;
stackdump (e, &c); open_stackdumpfile ();
exception (e, in);
stackdump ((DWORD) ebp, 0);
} }
try_to_debug ();
signal_exit (0x80 | sig); // Flag signal + core dump signal_exit (0x80 | sig); // Flag signal + core dump
} }
sig_send (NULL, sig, (DWORD) ebp, 1); // Signal myself sig_send (NULL, sig, (DWORD) ebp, 1); // Signal myself
@ -1017,30 +1001,30 @@ sig_handle (int sig)
goto dosig; goto dosig;
stop: stop:
/* Eat multiple attempts to STOP */ /* Eat multiple attempts to STOP */
if (ISSTATE (myself, PID_STOPPED)) if (ISSTATE (myself, PID_STOPPED))
goto done; goto done;
handler = (void *) sig_handle_tty_stop; handler = (void *) sig_handle_tty_stop;
thissig = myself->getsig (SIGSTOP); thissig = myself->getsig (SIGSTOP);
dosig: dosig:
/* Dispatch to the appropriate function. */ /* Dispatch to the appropriate function. */
sigproc_printf ("signal %d, about to call %p", sig, handler); sigproc_printf ("signal %d, about to call %p", sig, handler);
rc = setup_handler (sig, handler, thissig); rc = setup_handler (sig, handler, thissig);
done: done:
sigproc_printf ("returning %d", rc); sigproc_printf ("returning %d", rc);
return rc; return rc;
exit_sig: exit_sig:
if (sig == SIGQUIT || sig == SIGABRT) if (sig == SIGQUIT || sig == SIGABRT)
{ {
CONTEXT c; CONTEXT c;
c.ContextFlags = CONTEXT_FULL; c.ContextFlags = CONTEXT_FULL;
GetThreadContext (hMainThread, &c); GetThreadContext (hMainThread, &c);
stackdump (NULL, &c); if (!try_to_debug ())
try_to_debug (); stackdump (c.Ebp, 1);
sig |= 0x80; sig |= 0x80;
} }
sigproc_printf ("signal %d, about to call do_exit", sig); sigproc_printf ("signal %d, about to call do_exit", sig);

View File

@ -184,7 +184,7 @@ extern HANDLE netapi32_handle;
/* debug_on_trap support. see exceptions.cc:try_to_debug() */ /* debug_on_trap support. see exceptions.cc:try_to_debug() */
extern "C" void error_start_init (const char*); extern "C" void error_start_init (const char*);
extern "C" int try_to_debug (); extern "C" int try_to_debug (bool waitloop = 1);
extern int cygwin_finished_initializing; extern int cygwin_finished_initializing;