⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 exceptions.cc

📁 cygwin, 著名的在win32下模拟unix操作系统的东东
💻 CC
📖 第 1 页 / 共 3 页
字号:
     tells Windows to keep looking for an exception handler.  */  if (exit_already)    return 1;  /* Coerce win32 value to posix value.  */  switch (e->ExceptionCode)    {    case STATUS_FLOAT_DENORMAL_OPERAND:    case STATUS_FLOAT_DIVIDE_BY_ZERO:    case STATUS_FLOAT_INEXACT_RESULT:    case STATUS_FLOAT_INVALID_OPERATION:    case STATUS_FLOAT_OVERFLOW:    case STATUS_FLOAT_STACK_CHECK:    case STATUS_FLOAT_UNDERFLOW:    case STATUS_INTEGER_DIVIDE_BY_ZERO:    case STATUS_INTEGER_OVERFLOW:      sig = SIGFPE;      break;    case STATUS_ILLEGAL_INSTRUCTION:    case STATUS_PRIVILEGED_INSTRUCTION:    case STATUS_NONCONTINUABLE_EXCEPTION:      sig = SIGILL;      break;    case STATUS_TIMEOUT:      sig = SIGALRM;      break;    case STATUS_ACCESS_VIOLATION:    case STATUS_DATATYPE_MISALIGNMENT:    case STATUS_ARRAY_BOUNDS_EXCEEDED:    case STATUS_GUARD_PAGE_VIOLATION:    case STATUS_IN_PAGE_ERROR:    case STATUS_NO_MEMORY:    case STATUS_INVALID_DISPOSITION:    case STATUS_STACK_OVERFLOW:      sig = SIGSEGV;      break;    case STATUS_CONTROL_C_EXIT:      sig = SIGINT;      break;    case STATUS_INVALID_HANDLE:      /* CloseHandle will throw this exception if it is given an	 invalid handle.  We don't care about the exception; we just	 want CloseHandle to return an error.  This can be revisited	 if gcc ever supports Windows style structured exception	 handling.  */      return 0;    default:      /* If we don't recognize the exception, we have to assume that	 we are doing structured exception handling, and we let	 something else handle it.  */      return 1;    }  debug_printf ("In cygwin_except_handler exc %p at %p sp %p", e->ExceptionCode, in->Eip, in->Esp);  debug_printf ("In cygwin_except_handler sig = %d at %p", sig, in->Eip);  if (myself->getsig (sig).sa_mask & SIGTOMASK (sig))    syscall_printf ("signal %d, masked %p", sig, myself->getsig (sig).sa_mask);  debug_printf ("In cygwin_except_handler calling %p",		 myself->getsig (sig).sa_handler);  DWORD *ebp = (DWORD *)in->Esp;  for (DWORD *bpend = (DWORD *) __builtin_frame_address (0); ebp > bpend; ebp--)    if (*ebp == in->SegCs && ebp[-1] == in->Eip)      {	ebp -= 2;	break;      }  if (!myself->progname[0]      || GetCurrentThreadId () == sigtid      || (void *) myself->getsig (sig).sa_handler == (void *) SIG_DFL      || (void *) myself->getsig (sig).sa_handler == (void *) SIG_IGN      || (void *) myself->getsig (sig).sa_handler == (void *) SIG_ERR)    {      /* Print the exception to the console */      if (e)	{	  for (int i = 0; status_info[i].name; i++)	    {	      if (status_info[i].code == e->ExceptionCode)		{		  if (!myself->ppid_handle)		    system_printf ("Exception: %s", status_info[i].name);		  break;		}	    }	}      /* Another exception could happen while tracing or while exiting.	 Only do this once.  */      if (recursed++)	system_printf ("Error while dumping state (probably corrupted stack)");      else	{	  if (try_to_debug (0))	    {	      debugging = 1;	      return 0;	    }	  open_stackdumpfile ();	  exception (e, in);	  stackdump ((DWORD) ebp, 0, 1);	}      signal_exit (0x80 | sig);	// Flag signal + core dump    }  sig_send (NULL, sig, (DWORD) ebp, 1);		// Signal myself  return 0;}#endif /* __i386__ */#ifndef HAVE_STACK_TRACEvoidstack (void){  system_printf ("Stack trace not yet supported on this machine.");}#endif/* Utilities to call a user supplied exception handler.  */#define SIG_NONMASKABLE	(SIGTOMASK (SIGKILL) | SIGTOMASK (SIGSTOP))#ifdef __i386__#define HAVE_CALL_HANDLER/* Non-raceable sigsuspend * Note: This implementation is based on the Single UNIX Specification * man page.  This indicates that sigsuspend always returns -1 and that * attempts to block unblockable signals will be silently ignored. * This is counter to what appears to be documented in some UNIX * man pages, e.g. Linux. */int __stdcallhandle_sigsuspend (sigset_t tempmask){  sig_dispatch_pending (0);  sigframe thisframe (mainthread);  sigset_t oldmask = myself->getsigmask ();	// Remember for restoration  set_process_mask (tempmask & ~SIG_NONMASKABLE);// Let signals we're				//  interested in through.  sigproc_printf ("old mask %x, new mask %x", oldmask, tempmask);  WaitForSingleObject (signal_arrived, INFINITE);  set_sig_errno (EINTR);	// Per POSIX  /* A signal dispatch function will have been added to our stack and will     be hit eventually.  Set the old mask to be restored when the signal     handler returns. */  sigsave.oldmask = oldmask;	// Will be restored by signal handler  return -1;}extern DWORD exec_exit;		// Possible exit value for execextern int pending_signals;extern "C" {static voidsig_handle_tty_stop (int sig){  /* Silently ignore attempts to suspend if there is no accomodating     cygwin parent to deal with this behavior. */  if (!myself->ppid_handle)    {      myself->process_state &= ~PID_STOPPED;      return;    }  myself->stopsig = sig;  /* See if we have a living parent.  If so, send it a special signal.   * It will figure out exactly which pid has stopped by scanning   * its list of subprocesses.   */  if (my_parent_is_alive ())    {      pinfo parent (myself->ppid);      if (!(parent->getsig (SIGCHLD).sa_flags & SA_NOCLDSTOP))	sig_send (parent, SIGCHLD);    }  sigproc_printf ("process %d stopped by signal %d, myself->ppid_handle %p",		  myself->pid, sig, myself->ppid_handle);  if (WaitForSingleObject (sigCONT, INFINITE) != WAIT_OBJECT_0)    api_fatal ("WaitSingleObject failed, %E");  (void) ResetEvent (sigCONT);  return;}}intinterruptible (DWORD pc, int testvalid = 0){  int res;  MEMORY_BASIC_INFORMATION m;  memset (&m, 0, sizeof m);  if (!VirtualQuery ((LPCVOID) pc, &m, sizeof m))    sigproc_printf ("couldn't get memory info, pc %p, %E", pc);  char *checkdir = (char *) alloca (windows_system_directory_length + 4);  memset (checkdir, 0, sizeof (checkdir));# define h ((HMODULE) m.AllocationBase)  /* Apparently Windows 95 can sometimes return bogus addresses from     GetThreadContext.  These resolve to a strange allocation base.     These should *never* be treated as interruptible. */  if (!h || m.State != MEM_COMMIT)    res = 0;  else if (testvalid)    res = 1;	/* All we wanted to know was if this was a valid module. */  else if (h == user_data->hmodule)    res = 1;  else if (h == cygwin_hmodule)    res = 0;  else if (!GetModuleFileName (h, checkdir, windows_system_directory_length + 2))    res = 0;  else    res = !strncasematch (windows_system_directory, checkdir,			  windows_system_directory_length);  sigproc_printf ("pc %p, h %p, interruptible %d, testvalid %d", pc, h, res, testvalid);# undef h  return res;}boolsigthread::get_winapi_lock (int test){  if (test)    return !InterlockedExchange (&winapi_lock, 1);  /* Need to do a busy loop because we can't block or a potential SuspendThread     will hang. */  while (InterlockedExchange (&winapi_lock, 1))    low_priority_sleep (0);  return 1;}voidsigthread::release_winapi_lock (){  /* Assumes that we have the lock. */  InterlockedExchange (&winapi_lock, 0);}static void __stdcall interrupt_setup (int sig, void *handler, DWORD retaddr,				       DWORD *retaddr_on_stack,				       struct sigaction& siga)		      __attribute__((regparm(3)));static void __stdcallinterrupt_setup (int sig, void *handler, DWORD retaddr, DWORD *retaddr_on_stack,		 struct sigaction& siga){  sigsave.retaddr = retaddr;  sigsave.retaddr_on_stack = retaddr_on_stack;  /* FIXME: Not multi-thread aware */  sigsave.oldmask = myself->getsigmask ();  sigsave.newmask = sigsave.oldmask | siga.sa_mask | SIGTOMASK (sig);  sigsave.sa_flags = siga.sa_flags;  sigsave.func = (void (*)(int)) handler;  sigsave.sig = sig;  sigsave.saved_errno = -1;		// Flag: no errno to save  if (handler == sig_handle_tty_stop)    {      myself->stopsig = 0;      myself->process_state |= PID_STOPPED;    }  /* Clear any waiting threads prior to dispatching to handler function */  proc_subproc (PROC_CLEARWAIT, 1);  int res = SetEvent (signal_arrived);	// For an EINTR case  sigproc_printf ("armed signal_arrived %p, res %d", signal_arrived, res);}static bool interrupt_now (CONTEXT *, int, void *, struct sigaction&) __attribute__((regparm(3)));static boolinterrupt_now (CONTEXT *ctx, int sig, void *handler, struct sigaction& siga){  interrupt_setup (sig, handler, ctx->Eip, 0, siga);  ctx->Eip = (DWORD) sigdelayed;  SetThreadContext (myself->getthread2signal (), ctx); /* Restart the thread in a new location */  return 1;}void __stdcallsignal_fixup_after_fork (){  if (sigsave.sig)    {      sigsave.sig = 0;      if (sigsave.retaddr_on_stack)	{	  *sigsave.retaddr_on_stack = sigsave.retaddr;	  set_process_mask (sigsave.oldmask);	}    }  sigproc_init ();}void __stdcallsignal_fixup_after_exec (bool isspawn){  /* Set up child's signal handlers */  for (int i = 0; i < NSIG; i++)    {      myself->getsig (i).sa_mask = 0;      if (myself->getsig (i).sa_handler != SIG_IGN || isspawn)	myself->getsig (i).sa_handler = SIG_DFL;    }}static int interrupt_on_return (sigthread *, int, void *, struct sigaction&) __attribute__((regparm(3)));static intinterrupt_on_return (sigthread *th, int sig, void *handler, struct sigaction& siga){  int i;  DWORD ebp = th->frame;  if (!ebp)    return 0;  thestack.init (ebp, 0, 1);  /* Initialize from the input CONTEXT */  for (i = 0; i < 32 && thestack++ ; i++)    if (th->exception || interruptible (thestack.sf.AddrReturn.Offset))      {	DWORD *addr_retaddr = ((DWORD *)thestack.sf.AddrFrame.Offset) + 1;	if (*addr_retaddr  == thestack.sf.AddrReturn.Offset)	  {	    interrupt_setup (sig, handler, *addr_retaddr, addr_retaddr, siga);	    *addr_retaddr = (DWORD) sigdelayed;	  }	return 1;      }  sigproc_printf ("couldn't find a stack frame, i %d", i);  return 0;}extern "C" void __stdcallset_sig_errno (int e){  set_errno (e);  sigsave.saved_errno = e;  // sigproc_printf ("errno %d", e);}static int setup_handler (int, void *, struct sigaction&) __attribute__((regparm(3)));static intsetup_handler (int sig, void *handler, struct sigaction& siga){  CONTEXT cx;  bool interrupted = false;  sigthread *th = NULL;		// Initialization needed to shut up gcc  int prio = INFINITE;  if (sigsave.sig)    goto set_pending;  for (int i = 0; i < CALL_HANDLER_RETRY; i++)    {      DWORD res;      HANDLE hth;      EnterCriticalSection (&mainthread.lock);      if (mainthread.frame)	{	  hth = NULL;	  th = &mainthread;	}      else	{	  LeaveCriticalSection (&mainthread.lock);	  if (!mainthread.get_winapi_lock (1))	    continue;	  hth = myself->getthread2signal ();	  th = NULL;	  /* Suspend the thread which will receive the signal.  But first ensure that	     this thread doesn't have any mutos.  (FIXME: Someday we should just grab	     all of the mutos rather than checking for them)	     For Windows 95, we also have to ensure that the addresses returned by GetThreadContext	     are valid.	     If one of these conditions is not true we loop for a fixed number of times	     since we don't want to stall the signal handler.  FIXME: Will this result in	     noticeable delays?	     If the thread is already suspended (which can occur when a program has called	     SuspendThread on itself then just queue the signal. */	  EnterCriticalSection (&mainthread.lock);	  sigproc_printf ("suspending mainthread");	  res = SuspendThread (hth);	  /* Just release the lock now since we hav suspended the main thread and it	     definitely can't be grabbing it now.  This will have to change, of course,	     if/when we can send signals to other than the main thread. */	  LeaveCriticalSection (&mainthread.lock);	  /* Just set pending if thread is already suspended */	  if (res)	    {	      (void) ResumeThread (hth);	      break;	    }	  mainthread.release_winapi_lock ();	  if (mainthread.frame)	    goto resume_thread;	/* We just got the frame.  What are the odds?				   Just loop and we'll hopefully pick it up on				   the next pass through. */	  muto *m;	  /* FIXME: Make multi-thread aware */	  for (m = muto_start.next;  m != NULL; m = m->next)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -