* 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