* 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
 | ||||
|     } | ||||
| 
 | ||||
|  | @ -1017,30 +1001,30 @@ sig_handle (int sig) | |||
| 
 | ||||
|   goto dosig; | ||||
| 
 | ||||
| stop: | ||||
|  stop: | ||||
|   /* Eat multiple attempts to STOP */ | ||||
|   if (ISSTATE (myself, PID_STOPPED)) | ||||
|     goto done; | ||||
|   handler = (void *) sig_handle_tty_stop; | ||||
|   thissig = myself->getsig (SIGSTOP); | ||||
| 
 | ||||
| dosig: | ||||
|  dosig: | ||||
|   /* Dispatch to the appropriate function. */ | ||||
|   sigproc_printf ("signal %d, about to call %p", sig, handler); | ||||
|   rc = setup_handler (sig, handler, thissig); | ||||
| 
 | ||||
| done: | ||||
|  done: | ||||
|   sigproc_printf ("returning %d", rc); | ||||
|   return rc; | ||||
| 
 | ||||
| exit_sig: | ||||
|  exit_sig: | ||||
|   if (sig == SIGQUIT || sig == SIGABRT) | ||||
|     { | ||||
|       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