📄 exceptions.cc
字号:
if (m->unstable () || m->owner () == mainthread.id) { sigproc_printf ("suspended thread owns a muto (%s)", m->name); goto resume_thread; } if (mainthread.frame) th = &mainthread; else { cx.ContextFlags = CONTEXT_CONTROL | CONTEXT_INTEGER; if (!GetThreadContext (hth, &cx)) { system_printf ("couldn't get context of main thread, %E"); goto resume_thread; } } } if ((DWORD) prio != INFINITE) { /* Reset the priority so we can finish this off quickly. */ SetThreadPriority (GetCurrentThread (), WAIT_SIG_PRIORITY); prio = INFINITE; } if (th) { interrupted = interrupt_on_return (th, sig, handler, siga); LeaveCriticalSection (&th->lock); } else if (interruptible (cx.Eip)) interrupted = interrupt_now (&cx, sig, handler, siga); resume_thread: if (hth) res = ResumeThread (hth); if (interrupted) break; if ((DWORD) prio != INFINITE && !mainthread.frame) prio = low_priority_sleep (SLEEP_0_STAY_LOW); sigproc_printf ("couldn't interrupt. trying again."); } set_pending: if (interrupted) { if ((DWORD) prio != INFINITE) SetThreadPriority (GetCurrentThread (), WAIT_SIG_PRIORITY); sigproc_printf ("signal successfully delivered"); } else { pending_signals = 1; /* FIXME: Probably need to be more tricky here */ sig_set_pending (sig); sig_dispatch_pending (1); low_priority_sleep (SLEEP_0_STAY_LOW); /* Hopefully, other process will be waking up soon. */ sigproc_printf ("couldn't send signal %d", sig); } sigproc_printf ("returning %d", interrupted); return interrupted;}#endif /* i386 */#ifndef HAVE_CALL_HANDLER#error "Need to supply machine dependent setup_handler"#endif/* Keyboard interrupt handler. */static BOOL WINAPIctrl_c_handler (DWORD type){ if (type == CTRL_LOGOFF_EVENT) return TRUE; /* Return FALSE to prevent an "End task" dialog box from appearing for each Cygwin process window that's open when the computer is shut down or console window is closed. */ if (type == CTRL_SHUTDOWN_EVENT) { sig_send (NULL, SIGTERM); return FALSE; } if (type == CTRL_CLOSE_EVENT) { sig_send (NULL, SIGHUP); return FALSE; } /* If we are a stub and the new process has a pinfo structure, let it handle this signal. */ if (dwExeced && pinfo (dwExeced)) return TRUE; /* We're only the process group leader when we have a valid pinfo structure. If we don't have one, then the parent "stub" will handle the signal. */ if (!pinfo (cygwin_pid (GetCurrentProcessId ()))) return TRUE; tty_min *t = cygwin_shared->tty.get_tty (myself->ctty); /* Ignore this if we're not the process group leader since it should be handled *by* the process group leader. */ if (myself->ctty != -1 && t->getpgid () == myself->pid && (GetTickCount () - t->last_ctrl_c) >= MIN_CTRL_C_SLOP) /* Otherwise we just send a SIGINT to the process group and return TRUE (to indicate that we have handled the signal). At this point, type should be a CTRL_C_EVENT or CTRL_BREAK_EVENT. */ { t->last_ctrl_c = GetTickCount (); kill (-myself->pid, SIGINT); t->last_ctrl_c = GetTickCount (); return TRUE; } return TRUE;}/* Set the signal mask for this process. Note that some signals are unmaskable, as in UNIX. */extern "C" void __stdcallset_process_mask (sigset_t newmask){ sigframe thisframe (mainthread); mask_sync->acquire (INFINITE); sigset_t oldmask = myself->getsigmask (); newmask &= ~SIG_NONMASKABLE; sigproc_printf ("old mask = %x, new mask = %x", myself->getsigmask (), newmask); myself->setsigmask (newmask); // Set a new mask mask_sync->release (); if (oldmask != newmask && GetCurrentThreadId () != sigtid) sig_dispatch_pending (); else sigproc_printf ("not calling sig_dispatch_pending. sigtid %p current %p", sigtid, GetCurrentThreadId ()); return;}int __stdcallsig_handle (int sig, bool thisproc){ int rc = 0; sigproc_printf ("signal %d", sig); struct sigaction thissig = myself->getsig (sig); void *handler = (void *) thissig.sa_handler; myself->rusage_self.ru_nsignals++; /* Clear pending SIGCONT on stop signals */ if (sig == SIGSTOP || sig == SIGTSTP || sig == SIGTTIN || sig == SIGTTOU) sig_clear (SIGCONT); if (sig == SIGKILL) goto exit_sig; if (sig == SIGSTOP) goto stop; /* FIXME: Should we still do this if SIGCONT has a handler? */ if (sig == SIGCONT) { DWORD stopped = myself->process_state & PID_STOPPED; myself->stopsig = 0; myself->process_state &= ~PID_STOPPED; /* Clear pending stop signals */ sig_clear (SIGSTOP); sig_clear (SIGTSTP); sig_clear (SIGTTIN); sig_clear (SIGTTOU); if (stopped) SetEvent (sigCONT); /* process pending signals */ sig_dispatch_pending (1); }#if 0 char sigmsg[24]; __small_sprintf (sigmsg, "cygwin: signal %d\n", sig); OutputDebugString (sigmsg);#endif if (handler == (void *) SIG_DFL) { if (sig == SIGCHLD || sig == SIGIO || sig == SIGCONT || sig == SIGWINCH || sig == SIGURG || (thisproc && hExeced && sig == SIGINT)) { sigproc_printf ("default signal %d ignored", sig); goto done; } if (sig == SIGTSTP || sig == SIGTTIN || sig == SIGTTOU) goto stop; goto exit_sig; } if (handler == (void *) SIG_IGN) { sigproc_printf ("signal %d ignored", sig); goto done; } if (handler == (void *) SIG_ERR) goto exit_sig; goto dosig; stop: /* Eat multiple attempts to STOP */ if (ISSTATE (myself, PID_STOPPED)) goto done; handler = (void *) sig_handle_tty_stop; thissig = myself->getsig (SIGSTOP); dosig: /* Dispatch to the appropriate function. */ sigproc_printf ("signal %d, about to call %p", sig, handler); rc = setup_handler (sig, handler, thissig); done: sigproc_printf ("returning %d", rc); return rc; exit_sig: if (sig == SIGQUIT || sig == SIGABRT) { CONTEXT c; c.ContextFlags = CONTEXT_FULL; GetThreadContext (hMainThread, &c); if (!try_to_debug ()) stackdump (c.Ebp, 1, 1); sig |= 0x80; } sigproc_printf ("signal %d, about to call do_exit", sig); signal_exit (sig); /* Never returns */}/* Cover function to `do_exit' to handle exiting even in presence of more exceptions. We used to call exit, but a SIGSEGV shouldn't cause atexit routines to run. */static voidsignal_exit (int rc){ rc = EXIT_SIGNAL | (rc << 8); if (exit_already++) myself->exit (rc); /* We'd like to stop the main thread from executing but when we do that it causes random, inexplicable hangs. So, instead, we set up the priority of this thread really high so that it should do its thing and then exit. */ (void) SetThreadPriority (hMainThread, THREAD_PRIORITY_IDLE); (void) SetThreadPriority (GetCurrentThread (), THREAD_PRIORITY_TIME_CRITICAL); /* Unlock any main thread mutos since we're executing with prejudice. */ muto *m; for (m = muto_start.next; m != NULL; m = m->next) if (m->unstable () || m->owner () == mainthread.id) m->reset (); user_data->resourcelocks->Delete (); user_data->resourcelocks->Init (); if (hExeced) TerminateProcess (hExeced, rc); sigproc_printf ("about to call do_exit (%x)", rc); do_exit (rc);}HANDLE NO_COPY title_mutex = NULL;voidevents_init (void){ /* title_mutex protects modification of console title. It's neccessary while finding console window handle */ if (!(title_mutex = CreateMutex (&sec_all_nih, FALSE, shared_name ("title_mutex", 0)))) api_fatal ("can't create title mutex, %E"); ProtectHandle (title_mutex); new_muto (mask_sync); windows_system_directory[0] = '\0'; (void) GetSystemDirectory (windows_system_directory, sizeof (windows_system_directory) - 2); char *end = strchr (windows_system_directory, '\0'); if (end == windows_system_directory) api_fatal ("can't find windows system directory"); if (end[-1] != '\\') { *end++ = '\\'; *end = '\0'; } windows_system_directory_length = end - windows_system_directory; debug_printf ("windows_system_directory '%s', windows_system_directory_length %d", windows_system_directory, windows_system_directory_length); debug_printf ("cygwin_hmodule %p", cygwin_hmodule);}voidevents_terminate (void){ exit_already = 1;}extern "C" {static int __stdcallcall_signal_handler_now (){ if (!sigsave.sig) { sigproc_printf ("call_signal_handler_now called when no signal active"); return 0; } int sa_flags = sigsave.sa_flags; sigproc_printf ("sa_flags %p", sa_flags); *sigsave.retaddr_on_stack = sigsave.retaddr; sigdelayed0 (); return sa_flags & SA_RESTART;}/* This kludge seems to keep a copy of call_signal_handler_now around even when compiling with -finline-functions. */static int __stdcall call_signal_handler_now_dummy () __attribute__((alias ("call_signal_handler_now")));};intsigframe::call_signal_handler (){ return unregister () ? call_signal_handler_now () : 0;}#define pid_offset (unsigned)(((_pinfo *)NULL)->pid)extern "C" {void __stdcallreset_signal_arrived (){ (void) ResetEvent (signal_arrived); sigproc_printf ("reset signal_arrived");}static void unused_sig_wrapper () __attribute__((const, unused));#undef errno#define errno ((DWORD volatile) _impure_ptr) + (((char *) &_impure_ptr->_errno) - ((char *) _impure_ptr))static voidunused_sig_wrapper (){/* Signal cleanup stuff. Cleans up stack (too bad that we didn't prototype signal handlers as __stdcall), calls _set_process_mask to restore any mask, restores any potentially clobbered registers and returns to original caller. */__asm__ volatile ("\n\ .text \n\_sigreturn: \n\ addl $4,%%esp # Remove argument \n\ movl %%esp,%%ebp \n\ addl $36,%%ebp \n\ call _set_process_mask@4 \n\ \n\ cmpl $0,%4 # Did a signal come in? \n\ jz 1f # No, if zero \n\ call _call_signal_handler_now@0 # yes handle the signal \n\ \n\1: popl %%eax # saved errno \n\ testl %%eax,%%eax # Is it < 0 \n\ jl 2f # yup. ignore it \n\ movl %1,%%ebx \n\ movl %%eax,(%%ebx) \n\2: popl %%eax \n\ popl %%ebx \n\ popl %%ecx \n\ popl %%edx \n\ popl %%edi \n\ popl %%esi \n\ popf \n\ popl %%ebp \n\ ret \n\ \n\__no_sig_start: \n\_sigdelayed: \n\ pushl %2 # original return address \n\_sigdelayed0: \n\ pushl %%ebp \n\ movl %%esp,%%ebp \n\ pushf \n\ pushl %%esi \n\ pushl %%edi \n\ pushl %%edx \n\ pushl %%ecx \n\ pushl %%ebx \n\ pushl %%eax \n\ pushl %6 # saved errno \n\ pushl %3 # oldmask \n\ pushl %4 # signal argument \n\ pushl $_sigreturn \n\ \n\ call _reset_signal_arrived@0 \n\ pushl %5 # signal number \n\ pushl %7 # newmask \n\ movl $0,%0 # zero the signal number as a \n\ # flag to the signal handler thread\n\ # that it is ok to set up sigsave\n\ \n\ call _set_process_mask@4 \n\ popl %%eax \n\ jmp *%%eax \n\__no_sig_end: \n\" : "=m" (sigsave.sig): "X" ((char *) &_impure_ptr->_errno), "g" (sigsave.retaddr), "g" (sigsave.oldmask), "g" (sigsave.sig), "g" (sigsave.func), "g" (sigsave.saved_errno), "g" (sigsave.newmask));}}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -