* 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>
|
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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue