* 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:
parent
2b5803d4b7
commit
8abeff1ead
|
@ -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>
|
||||
|
||||
* path.cc (symlink_info::check): Remove extra arguments, move
|
||||
|
|
|
@ -109,8 +109,6 @@ init_exception_handler (exception_list *el)
|
|||
el->prev = _except_list;
|
||||
_except_list = el;
|
||||
}
|
||||
|
||||
#define INIT_EXCEPTION_HANDLER(el) init_exception_handler (el)
|
||||
#endif
|
||||
|
||||
void
|
||||
|
@ -134,9 +132,7 @@ set_console_handler ()
|
|||
extern "C" void
|
||||
init_exceptions (exception_list *el)
|
||||
{
|
||||
#ifdef INIT_EXCEPTION_HANDLER
|
||||
INIT_EXCEPTION_HANDLER (el);
|
||||
#endif
|
||||
init_exception_handler (el);
|
||||
}
|
||||
|
||||
extern "C" void
|
||||
|
@ -155,6 +151,29 @@ error_start_init (const char *buf)
|
|||
__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. */
|
||||
|
||||
static void
|
||||
|
@ -201,13 +220,11 @@ exception (EXCEPTION_RECORD *e, CONTEXT *in)
|
|||
/* A class for manipulating the stack. */
|
||||
class stack_info
|
||||
{
|
||||
int first_time; /* True if just starting to iterate. */
|
||||
int walk (); /* Uses the "old" method */
|
||||
char *next_offset () {return *((char **) sf.AddrFrame.Offset);}
|
||||
public:
|
||||
STACKFRAME sf; /* For storing the stack information */
|
||||
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. */
|
||||
int operator ++(int) { return this->walk (); }
|
||||
|
@ -224,11 +241,12 @@ static signal_dispatch sigsave;
|
|||
void
|
||||
stack_info::init (DWORD ebp)
|
||||
{
|
||||
first_time = 1;
|
||||
# define debp ((DWORD *) ebp)
|
||||
memset (&sf, 0, sizeof (sf));
|
||||
sf.AddrFrame.Offset = ebp;
|
||||
sf.AddrPC.Offset = ((DWORD *) ebp)[1];
|
||||
sf.AddrReturn.Offset = debp[1];
|
||||
sf.AddrFrame.Mode = AddrModeFlat;
|
||||
# undef debp
|
||||
}
|
||||
|
||||
/* Walk the stack by looking at successive stored 'bp' frames.
|
||||
|
@ -237,10 +255,7 @@ int
|
|||
stack_info::walk ()
|
||||
{
|
||||
char **ebp;
|
||||
if (first_time)
|
||||
/* Everything is filled out already */
|
||||
ebp = (char **) sf.AddrFrame.Offset;
|
||||
else if ((ebp = (char **) next_offset ()) != NULL)
|
||||
if ((ebp = (char **) next_offset ()) != NULL)
|
||||
{
|
||||
sf.AddrFrame.Offset = (DWORD) ebp;
|
||||
sf.AddrPC.Offset = sf.AddrReturn.Offset;
|
||||
|
@ -248,7 +263,6 @@ stack_info::walk ()
|
|||
else
|
||||
return 0;
|
||||
|
||||
first_time = 0;
|
||||
if (!sf.AddrPC.Offset)
|
||||
return 0; /* stack frames are exhausted */
|
||||
|
||||
|
@ -261,13 +275,20 @@ stack_info::walk ()
|
|||
return 1;
|
||||
}
|
||||
|
||||
/* Dump the stack */
|
||||
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;
|
||||
|
||||
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");
|
||||
for (i = 0; i < 16 && thestack++; i++)
|
||||
{
|
||||
|
@ -288,15 +309,13 @@ cygwin_stackdump ()
|
|||
CONTEXT c;
|
||||
c.ContextFlags = CONTEXT_FULL;
|
||||
GetThreadContext (GetCurrentThread (), &c);
|
||||
stack (&c);
|
||||
stackdump (c.Ebp, 0);
|
||||
}
|
||||
|
||||
static int NO_COPY keep_looping = 0;
|
||||
|
||||
#define TIME_TO_WAIT_FOR_DEBUGGER 10000
|
||||
|
||||
extern "C" int
|
||||
try_to_debug ()
|
||||
try_to_debug (bool waitloop)
|
||||
{
|
||||
debug_printf ("debugger_command '%s'", debugger_command);
|
||||
if (*debugger_command == '\0')
|
||||
|
@ -306,6 +325,7 @@ try_to_debug ()
|
|||
|
||||
BOOL dbg;
|
||||
|
||||
SetThreadPriority (hMainThread, THREAD_PRIORITY_HIGHEST);
|
||||
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};
|
||||
|
@ -348,73 +368,37 @@ try_to_debug ()
|
|||
NULL,
|
||||
&si,
|
||||
&pi);
|
||||
if (!dbg)
|
||||
|
||||
static int NO_COPY keep_looping = 0;
|
||||
|
||||
if (dbg)
|
||||
{
|
||||
if (!waitloop)
|
||||
return 1;
|
||||
SetThreadPriority (hMainThread, THREAD_PRIORITY_IDLE);
|
||||
while (keep_looping)
|
||||
/* spin */;
|
||||
}
|
||||
|
||||
|
||||
system_printf ("Failed to start debugger: %E");
|
||||
/* FIXME: need to know handles of all running threads to
|
||||
resume_all_threads_except (current_thread_id);
|
||||
*/
|
||||
}
|
||||
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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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. */
|
||||
|
||||
static int
|
||||
handle_exceptions (EXCEPTION_RECORD *e, void *, CONTEXT *in, void *)
|
||||
{
|
||||
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
|
||||
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_ERR)
|
||||
{
|
||||
static NO_COPY int traced = 0;
|
||||
|
||||
/* Print the exception to the console */
|
||||
if (e)
|
||||
{
|
||||
|
@ -516,19 +498,21 @@ handle_exceptions (EXCEPTION_RECORD *e, void *, CONTEXT *in, void *)
|
|||
|
||||
/* Another exception could happen while tracing or while exiting.
|
||||
Only do this once. */
|
||||
if (traced++)
|
||||
if (recursed++)
|
||||
system_printf ("Error while dumping state (probably corrupted stack)");
|
||||
else
|
||||
{
|
||||
CONTEXT c = *in;
|
||||
DWORD stack[6];
|
||||
stack[0] = in->Ebp;
|
||||
stack[1] = in->Eip;
|
||||
stack[2] = stack[3] = stack[4] = stack[5] = 0;
|
||||
c.Ebp = (DWORD) &stack;
|
||||
stackdump (e, &c);
|
||||
if (try_to_debug (0))
|
||||
{
|
||||
debugging = 1;
|
||||
return 0;
|
||||
}
|
||||
try_to_debug ();
|
||||
|
||||
open_stackdumpfile ();
|
||||
exception (e, in);
|
||||
stackdump ((DWORD) ebp, 0);
|
||||
}
|
||||
|
||||
signal_exit (0x80 | sig); // Flag signal + core dump
|
||||
}
|
||||
|
||||
|
@ -1039,8 +1023,8 @@ exit_sig:
|
|||
CONTEXT c;
|
||||
c.ContextFlags = CONTEXT_FULL;
|
||||
GetThreadContext (hMainThread, &c);
|
||||
stackdump (NULL, &c);
|
||||
try_to_debug ();
|
||||
if (!try_to_debug ())
|
||||
stackdump (c.Ebp, 1);
|
||||
sig |= 0x80;
|
||||
}
|
||||
sigproc_printf ("signal %d, about to call do_exit", sig);
|
||||
|
|
|
@ -184,7 +184,7 @@ extern HANDLE netapi32_handle;
|
|||
|
||||
/* debug_on_trap support. see exceptions.cc:try_to_debug() */
|
||||
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;
|
||||
|
||||
|
|
Loading…
Reference in New Issue