3 Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004 Red Hat, Inc.
5 This file is part of Cygwin.
7 This software is a copyrighted work licensed under the terms of the
8 Cygwin license. Please consult the file "CYGWIN_LICENSE" for
17 #include "exceptions.h"
24 #include "perthread.h"
25 #include "shared_info.h"
26 #include "perprocess.h"
28 #include "cygthread.h"
30 #define CALL_HANDLER_RETRY 20
32 char debugger_command[2 * CYG_MAX_PATH + 20];
35 static int handle_exceptions (EXCEPTION_RECORD *, void *, CONTEXT *, void *);
36 extern void sigdelayed ();
41 extern HANDLE hExeced;
42 extern DWORD dwExeced;
44 static BOOL WINAPI ctrl_c_handler (DWORD);
45 static void signal_exit (int) __attribute__ ((noreturn));
46 static char windows_system_directory[1024];
47 static size_t windows_system_directory_length;
49 /* This is set to indicate that we have already exited. */
51 static NO_COPY int exit_already = 0;
52 static NO_COPY muto *mask_sync = NULL;
61 { X (STATUS_ABANDONED_WAIT_0) },
62 { X (STATUS_ACCESS_VIOLATION) },
63 { X (STATUS_ARRAY_BOUNDS_EXCEEDED) },
64 { X (STATUS_BREAKPOINT) },
65 { X (STATUS_CONTROL_C_EXIT) },
66 { X (STATUS_DATATYPE_MISALIGNMENT) },
67 { X (STATUS_FLOAT_DENORMAL_OPERAND) },
68 { X (STATUS_FLOAT_DIVIDE_BY_ZERO) },
69 { X (STATUS_FLOAT_INEXACT_RESULT) },
70 { X (STATUS_FLOAT_INVALID_OPERATION) },
71 { X (STATUS_FLOAT_OVERFLOW) },
72 { X (STATUS_FLOAT_STACK_CHECK) },
73 { X (STATUS_FLOAT_UNDERFLOW) },
74 { X (STATUS_GUARD_PAGE_VIOLATION) },
75 { X (STATUS_ILLEGAL_INSTRUCTION) },
76 { X (STATUS_INTEGER_DIVIDE_BY_ZERO) },
77 { X (STATUS_INTEGER_OVERFLOW) },
78 { X (STATUS_INVALID_DISPOSITION) },
79 { X (STATUS_IN_PAGE_ERROR) },
80 { X (STATUS_NONCONTINUABLE_EXCEPTION) },
81 { X (STATUS_NO_MEMORY) },
82 { X (STATUS_PENDING) },
83 { X (STATUS_PRIVILEGED_INSTRUCTION) },
84 { X (STATUS_SINGLE_STEP) },
85 { X (STATUS_STACK_OVERFLOW) },
86 { X (STATUS_TIMEOUT) },
87 { X (STATUS_USER_APC) },
88 { X (STATUS_WAIT_0) },
93 /* Initialization code. */
95 // Set up the exception handler for the current thread. The PowerPC & Mips
96 // use compiler generated tables to set up the exception handlers for each
97 // region of code, and the kernel walks the call list until it finds a region
98 // of code that handles exceptions. The x86 on the other hand uses segment
99 // register fs, offset 0 to point to the current exception handler.
101 extern exception_list *_except_list asm ("%fs:0");
104 init_exception_handler (exception_list *el, exception_handler *eh)
107 el->prev = _except_list;
112 init_exceptions (exception_list *el)
114 init_exception_handler (el, handle_exceptions);
118 init_console_handler ()
120 (void) SetConsoleCtrlHandler (ctrl_c_handler, FALSE);
121 if (!SetConsoleCtrlHandler (ctrl_c_handler, TRUE))
122 system_printf ("SetConsoleCtrlHandler failed, %E");
126 error_start_init (const char *buf)
130 debugger_command[0] = '\0';
134 char pgm[CYG_MAX_PATH + 1];
135 if (!GetModuleFileName (NULL, pgm, CYG_MAX_PATH))
136 strcpy (pgm, "cygwin1.dll");
137 for (char *p = strchr (pgm, '\\'); p; p = strchr (p, '\\'))
140 __small_sprintf (debugger_command, "%s \"%s\"", buf, pgm);
144 open_stackdumpfile ()
146 if (myself->progname[0])
149 /* write to progname.stackdump if possible */
150 if (!myself->progname[0])
152 else if ((p = strrchr (myself->progname, '\\')))
155 p = myself->progname;
156 char corefile[strlen (p) + sizeof (".stackdump")];
157 __small_sprintf (corefile, "%s.stackdump", p);
158 HANDLE h = CreateFile (corefile, GENERIC_WRITE, 0, &sec_none_nih,
159 CREATE_ALWAYS, 0, 0);
160 if (h != INVALID_HANDLE_VALUE)
162 if (!myself->ppid_handle)
163 system_printf ("Dumping stack trace to %s", corefile);
165 debug_printf ("Dumping stack trace to %s", corefile);
166 SetStdHandle (STD_ERROR_HANDLE, h);
171 /* Utilities for dumping the stack, etc. */
174 exception (EXCEPTION_RECORD *e, CONTEXT *in)
176 const char *exception_name = NULL;
180 for (int i = 0; status_info[i].name; i++)
182 if (status_info[i].code == e->ExceptionCode)
184 exception_name = status_info[i].name;
193 small_printf ("Exception: %s at eip=%08x\r\n", exception_name, in->Eip);
195 small_printf ("Exception %d at eip=%08x\r\n", e->ExceptionCode, in->Eip);
196 small_printf ("eax=%08x ebx=%08x ecx=%08x edx=%08x esi=%08x edi=%08x\r\n",
197 in->Eax, in->Ebx, in->Ecx, in->Edx, in->Esi, in->Edi);
198 small_printf ("ebp=%08x esp=%08x program=%s\r\n",
199 in->Ebp, in->Esp, myself->progname);
200 small_printf ("cs=%04x ds=%04x es=%04x fs=%04x gs=%04x ss=%04x\r\n",
201 in->SegCs, in->SegDs, in->SegEs, in->SegFs, in->SegGs, in->SegSs);
205 system_printf ("Had an exception");
210 /* Print a stack backtrace. */
212 #define HAVE_STACK_TRACE
214 /* A class for manipulating the stack. */
217 int walk (); /* Uses the "old" method */
218 char *next_offset () {return *((char **) sf.AddrFrame.Offset);}
222 STACKFRAME sf; /* For storing the stack information */
223 void init (DWORD, bool, bool); /* Called the first time that stack info is needed */
225 /* Postfix ++ iterates over the stack, returning zero when nothing is left. */
226 int operator ++(int) { return walk (); }
229 /* The number of parameters used in STACKFRAME */
230 #define NPARAMS (sizeof (thestack.sf.Params) / sizeof (thestack.sf.Params[0]))
232 /* This is the main stack frame info for this process. */
233 static NO_COPY stack_info thestack;
235 /* Initialize everything needed to start iterating. */
237 stack_info::init (DWORD ebp, bool wantargs, bool goodframe)
239 # define debp ((DWORD *) ebp)
240 memset (&sf, 0, sizeof (sf));
242 sf.AddrFrame.Offset = ebp;
246 sf.AddrFrame.Offset = (DWORD) &dummy_frame;
248 sf.AddrReturn.Offset = debp[1];
249 sf.AddrFrame.Mode = AddrModeFlat;
254 /* Walk the stack by looking at successive stored 'bp' frames.
255 This is not foolproof. */
260 if ((ebp = (char **) next_offset ()) == NULL)
263 sf.AddrFrame.Offset = (DWORD) ebp;
264 sf.AddrPC.Offset = sf.AddrReturn.Offset;
266 if (!sf.AddrPC.Offset)
267 return 0; /* stack frames are exhausted */
269 /* The return address always follows the stack pointer */
270 sf.AddrReturn.Offset = (DWORD) *++ebp;
273 /* The arguments follow the return address */
274 for (unsigned i = 0; i < NPARAMS; i++)
275 sf.Params[i] = (DWORD) *++ebp;
281 stackdump (DWORD ebp, int open_file, bool isexception)
283 extern unsigned long rlim_core;
285 if (rlim_core == 0UL)
289 open_stackdumpfile ();
293 thestack.init (ebp, 1, !isexception); /* Initialize from the input CONTEXT */
294 small_printf ("Stack trace:\r\nFrame Function Args\r\n");
295 for (i = 0; i < 16 && thestack++; i++)
297 small_printf ("%08x %08x ", thestack.sf.AddrFrame.Offset,
298 thestack.sf.AddrPC.Offset);
299 for (unsigned j = 0; j < NPARAMS; j++)
300 small_printf ("%s%08x", j == 0 ? " (" : ", ", thestack.sf.Params[j]);
301 small_printf (")\r\n");
303 small_printf ("End of stack trace%s",
304 i == 16 ? " (more stack frames may be present)" : "");
307 /* Temporary (?) function for external callers to get a stack dump */
312 c.ContextFlags = CONTEXT_FULL;
313 GetThreadContext (GetCurrentThread (), &c);
314 stackdump (c.Ebp, 0, 0);
317 #define TIME_TO_WAIT_FOR_DEBUGGER 10000
320 try_to_debug (bool waitloop)
322 debug_printf ("debugger_command '%s'", debugger_command);
323 if (*debugger_command == '\0' || being_debugged ())
326 __small_sprintf (strchr (debugger_command, '\0'), " %u", GetCurrentProcessId ());
328 LONG prio = GetThreadPriority (GetCurrentThread ());
329 SetThreadPriority (GetCurrentThread (), THREAD_PRIORITY_HIGHEST);
330 PROCESS_INFORMATION pi = {NULL, 0, 0, 0};
332 STARTUPINFO si = {0, NULL, NULL, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL};
333 si.lpReserved = NULL;
338 /* FIXME: need to know handles of all running threads to
339 suspend_all_threads_except (current_thread_id);
342 /* if any of these mutexes is owned, we will fail to start any cygwin app
343 until trapped app exits */
345 ReleaseMutex (title_mutex);
347 /* prevent recursive exception handling */
348 char* rawenv = GetEnvironmentStrings () ;
349 for (char* p = rawenv; *p != '\0'; p = strchr (p, '\0') + 1)
351 if (strncmp (p, "CYGWIN=", strlen ("CYGWIN=")) == 0)
353 char* q = strstr (p, "error_start") ;
354 /* replace 'error_start=...' with '_rror_start=...' */
358 SetEnvironmentVariable ("CYGWIN", p + strlen ("CYGWIN=")) ;
364 console_printf ("*** starting debugger for pid %u\n",
365 cygwin_pid (GetCurrentProcessId ()));
367 dbg = CreateProcess (NULL,
372 CREATE_NEW_CONSOLE | CREATE_NEW_PROCESS_GROUP,
379 system_printf ("Failed to start debugger: %E");
384 SetThreadPriority (GetCurrentThread (), THREAD_PRIORITY_IDLE);
385 while (!being_debugged ())
390 console_printf ("*** continuing pid %u from debugger call (%d)\n",
391 cygwin_pid (GetCurrentProcessId ()), dbg);
393 SetThreadPriority (GetCurrentThread (), prio);
397 /* Main exception handler. */
399 extern "C" DWORD __stdcall RtlUnwind (void *, void *, void *, DWORD);
401 handle_exceptions (EXCEPTION_RECORD *e0, void *frame, CONTEXT *in0, void *)
403 static bool NO_COPY debugging = false;
404 static int NO_COPY recursed = 0;
406 if (debugging && ++debugging < 500000)
408 SetThreadPriority (hMainThread, THREAD_PRIORITY_NORMAL);
412 /* If we've already exited, don't do anything here. Returning 1
413 tells Windows to keep looking for an exception handler. */
417 EXCEPTION_RECORD e = *e0;
421 /* Coerce win32 value to posix value. */
422 switch (e.ExceptionCode)
424 case STATUS_FLOAT_DENORMAL_OPERAND:
425 case STATUS_FLOAT_DIVIDE_BY_ZERO:
426 case STATUS_FLOAT_INVALID_OPERATION:
427 case STATUS_FLOAT_STACK_CHECK:
428 si.si_signo = SIGFPE;
429 si.si_sigval.sival_int = FPE_FLTSUB;
431 case STATUS_FLOAT_INEXACT_RESULT:
432 si.si_signo = SIGFPE;
433 si.si_sigval.sival_int = FPE_FLTRES;
435 case STATUS_FLOAT_OVERFLOW:
436 si.si_signo = SIGFPE;
437 si.si_sigval.sival_int = FPE_FLTOVF;
439 case STATUS_FLOAT_UNDERFLOW:
440 si.si_signo = SIGFPE;
441 si.si_sigval.sival_int = FPE_FLTUND;
443 case STATUS_INTEGER_DIVIDE_BY_ZERO:
444 si.si_signo = SIGFPE;
445 si.si_sigval.sival_int = FPE_INTDIV;
447 case STATUS_INTEGER_OVERFLOW:
448 si.si_signo = SIGFPE;
449 si.si_sigval.sival_int = FPE_INTOVF;
452 case STATUS_ILLEGAL_INSTRUCTION:
453 si.si_signo = SIGILL;
454 si.si_sigval.sival_int = ILL_ILLOPC;
457 case STATUS_PRIVILEGED_INSTRUCTION:
458 si.si_signo = SIGILL;
459 si.si_sigval.sival_int = ILL_PRVOPC;
462 case STATUS_NONCONTINUABLE_EXCEPTION:
463 si.si_signo = SIGILL;
464 si.si_sigval.sival_int = ILL_ILLADR;
468 si.si_signo = SIGALRM;
469 si.si_sigval.sival_int = 0;
472 case STATUS_ACCESS_VIOLATION:
473 case STATUS_DATATYPE_MISALIGNMENT:
474 case STATUS_ARRAY_BOUNDS_EXCEEDED:
475 case STATUS_GUARD_PAGE_VIOLATION:
476 case STATUS_IN_PAGE_ERROR:
477 case STATUS_NO_MEMORY:
478 case STATUS_INVALID_DISPOSITION:
479 case STATUS_STACK_OVERFLOW:
480 si.si_signo = SIGSEGV;
481 si.si_sigval.sival_int = SEGV_MAPERR;
484 case STATUS_CONTROL_C_EXIT:
485 si.si_signo = SIGINT;
486 si.si_sigval.sival_int = 0;
489 case STATUS_INVALID_HANDLE:
490 /* CloseHandle will throw this exception if it is given an
491 invalid handle. We don't care about the exception; we just
492 want CloseHandle to return an error. This can be revisited
493 if gcc ever supports Windows style structured exception
498 /* If we don't recognize the exception, we have to assume that
499 we are doing structured exception handling, and we let
500 something else handle it. */
504 debug_printf ("In cygwin_except_handler exc %p at %p sp %p", e.ExceptionCode, in.Eip, in.Esp);
505 debug_printf ("In cygwin_except_handler sig = %d at %p", si.si_signo, in.Eip);
507 if (global_sigs[si.si_signo].sa_mask & SIGTOMASK (si.si_signo))
508 syscall_printf ("signal %d, masked %p", si.si_signo,
509 global_sigs[si.si_signo].sa_mask);
511 debug_printf ("In cygwin_except_handler calling %p",
512 global_sigs[si.si_signo].sa_handler);
514 DWORD *ebp = (DWORD *)in.Esp;
515 for (DWORD *bpend = (DWORD *) __builtin_frame_address (0); ebp > bpend; ebp--)
516 if (*ebp == in.SegCs && ebp[-1] == in.Eip)
522 if (!cygwin_finished_initializing
523 || GetCurrentThreadId () == sigtid
524 || (void *) global_sigs[si.si_signo].sa_handler == (void *) SIG_DFL
525 || (void *) global_sigs[si.si_signo].sa_handler == (void *) SIG_IGN
526 || (void *) global_sigs[si.si_signo].sa_handler == (void *) SIG_ERR)
528 /* Print the exception to the console */
529 for (int i = 0; status_info[i].name; i++)
530 if (status_info[i].code == e.ExceptionCode)
532 if (!myself->ppid_handle)
533 system_printf ("Exception: %s", status_info[i].name);
537 /* Another exception could happen while tracing or while exiting.
538 Only do this once. */
540 system_printf ("Error while dumping state (probably corrupted stack)");
543 if (try_to_debug (0))
549 open_stackdumpfile ();
551 stackdump ((DWORD) ebp, 0, 1);
554 signal_exit (0x80 | si.si_signo); // Flag signal + core dump
557 extern DWORD ret_here[];
558 RtlUnwind (frame, ret_here, e0, 0);
559 __asm__ volatile (".equ _ret_here,.");
562 si.si_code = SI_KERNEL;
563 si.si_errno = si.si_pid = si.si_uid = 0;
564 _my_tls.push ((__stack_t) ebp, true);
565 sig_send (NULL, si, &_my_tls); // Signal myself
568 #endif /* __i386__ */
570 #ifndef HAVE_STACK_TRACE
574 system_printf ("Stack trace not yet supported on this machine.");
578 /* Utilities to call a user supplied exception handler. */
580 #define SIG_NONMASKABLE (SIGTOMASK (SIGKILL) | SIGTOMASK (SIGSTOP))
583 #define HAVE_CALL_HANDLER
585 /* Non-raceable sigsuspend
586 * Note: This implementation is based on the Single UNIX Specification
587 * man page. This indicates that sigsuspend always returns -1 and that
588 * attempts to block unblockable signals will be silently ignored.
589 * This is counter to what appears to be documented in some UNIX
590 * man pages, e.g. Linux.
593 handle_sigsuspend (sigset_t tempmask)
595 sigset_t oldmask = myself->getsigmask (); // Remember for restoration
597 // Let signals we're interested in through.
598 set_signal_mask (tempmask &= ~SIG_NONMASKABLE, oldmask);
599 sigproc_printf ("oldmask %p, newmask %p", oldmask, tempmask);
601 pthread_testcancel ();
602 pthread::cancelable_wait (signal_arrived, INFINITE);
604 set_sig_errno (EINTR); // Per POSIX
606 /* A signal dispatch function will have been added to our stack and will
607 be hit eventually. Set the old mask to be restored when the signal
610 _my_tls.oldmask = oldmask; // Will be restored by signal handler
614 extern DWORD exec_exit; // Possible exit value for exec
618 sig_handle_tty_stop (int sig)
620 /* Silently ignore attempts to suspend if there is no accomodating
621 cygwin parent to deal with this behavior. */
622 if (!myself->ppid_handle)
624 myself->process_state &= ~PID_STOPPED;
628 myself->stopsig = sig;
629 /* See if we have a living parent. If so, send it a special signal.
630 It will figure out exactly which pid has stopped by scanning
631 its list of subprocesses. */
632 if (my_parent_is_alive ())
634 pinfo parent (myself->ppid);
635 if (NOTSTATE (parent, PID_NOCLDSTOP))
638 si.si_signo = SIGCHLD;
639 si.si_code = SI_KERNEL;
640 si.si_sigval.sival_int = CLD_STOPPED;
641 si.si_errno = si.si_pid = si.si_uid = si.si_errno = 0;
642 sig_send (parent, si);
645 sigproc_printf ("process %d stopped by signal %d, myself->ppid_handle %p",
646 myself->pid, sig, myself->ppid_handle);
649 w4[1] = signal_arrived;
650 switch (WaitForMultipleObjects (2, w4, TRUE, INFINITE))
653 case WAIT_OBJECT_0 + 1:
654 reset_signal_arrived ();
657 api_fatal ("WaitSingleObject failed, %E");
665 interruptible (DWORD pc)
668 MEMORY_BASIC_INFORMATION m;
670 memset (&m, 0, sizeof m);
671 if (!VirtualQuery ((LPCVOID) pc, &m, sizeof m))
672 sigproc_printf ("couldn't get memory info, pc %p, %E", pc);
674 char *checkdir = (char *) alloca (windows_system_directory_length + 4);
675 memset (checkdir, 0, sizeof (checkdir));
677 # define h ((HMODULE) m.AllocationBase)
678 /* Apparently Windows 95 can sometimes return bogus addresses from
679 GetThreadContext. These resolve to a strange allocation base.
680 These should *never* be treated as interruptible. */
681 if (!h || m.State != MEM_COMMIT)
683 else if (h == user_data->hmodule)
685 else if (!GetModuleFileName (h, checkdir, windows_system_directory_length + 2))
688 res = !strncasematch (windows_system_directory, checkdir,
689 windows_system_directory_length);
690 sigproc_printf ("pc %p, h %p, interruptible %d", pc, h, res);
695 _cygtls::interrupt_setup (int sig, void *handler,
696 struct sigaction& siga)
698 push ((__stack_t) sigdelayed, false);
699 oldmask = myself->getsigmask ();
700 newmask = oldmask | siga.sa_mask | SIGTOMASK (sig);
701 sa_flags = siga.sa_flags;
702 func = (void (*) (int)) handler;
703 saved_errno = -1; // Flag: no errno to save
704 if (handler == sig_handle_tty_stop)
707 myself->process_state |= PID_STOPPED;
710 this->sig = sig; // Should ALWAYS be last setting set to avoid a race
712 /* Clear any waiting threads prior to dispatching to handler function */
713 int res = SetEvent (signal_arrived); // For an EINTR case
714 proc_subproc (PROC_CLEARWAIT, 1);
715 sigproc_printf ("armed signal_arrived %p, sig %d, res %d", signal_arrived,
720 _cygtls::interrupt_now (CONTEXT *ctx, int sig, void *handler,
721 struct sigaction& siga)
723 push ((__stack_t) ctx->Eip, false);
724 interrupt_setup (sig, handler, siga);
726 SetThreadContext (*this, ctx); /* Restart the thread in a new location */
730 extern "C" void __stdcall
731 set_sig_errno (int e)
733 *_my_tls.errno_addr = e;
734 _my_tls.saved_errno = e;
735 // sigproc_printf ("errno %d", e);
738 static int setup_handler (int, void *, struct sigaction&, _cygtls *tls)
739 __attribute__((regparm(3)));
741 setup_handler (int sig, void *handler, struct sigaction& siga, _cygtls *tls)
744 bool interrupted = false;
749 sigproc_printf ("trying to send sig %d but signal %d already armed",
754 for (int i = 0; i < CALL_HANDLER_RETRY; i++)
758 if (tls->stackptr > tls->stack)
760 tls->reset_exception ();
761 tls->interrupt_setup (sig, handler, siga);
762 sigproc_printf ("interrupted known cygwin routine");
770 HANDLE hth = (HANDLE) *tls;
772 /* Suspend the thread which will receive the signal.
773 For Windows 95, we also have to ensure that the addresses returned by
774 GetThreadContext are valid.
775 If one of these conditions is not true we loop for a fixed number of times
776 since we don't want to stall the signal handler. FIXME: Will this result in
778 If the thread is already suspended (which can occur when a program has called
779 SuspendThread on itself then just queue the signal. */
782 sigproc_printf ("suspending mainthread");
784 cx.ContextFlags = CONTEXT_CONTROL | CONTEXT_INTEGER;
785 if (!GetThreadContext (hth, &cx))
786 memset (&cx, 0, sizeof cx);
787 sigproc_printf ("suspending mainthread PC %p", cx.Eip);
789 res = SuspendThread (hth);
790 /* Just set pending if thread is already suspended */
791 if (res || tls->stackptr > tls->stack)
793 (void) ResumeThread (hth);
796 if (!tls->locked () && !tls->spinning)
798 cx.ContextFlags = CONTEXT_CONTROL | CONTEXT_INTEGER;
799 if (!GetThreadContext (hth, &cx))
800 system_printf ("couldn't get context of main thread, %E");
801 else if (interruptible (cx.Eip))
802 interrupted = tls->interrupt_now (&cx, sig, handler, siga);
805 res = ResumeThread (hth);
809 sigproc_printf ("couldn't interrupt. trying again.");
810 low_priority_sleep (0);
816 sigproc_printf ("signal %d %sdelivered", sig, interrupted ? "" : "not ");
821 #ifndef HAVE_CALL_HANDLER
822 #error "Need to supply machine dependent setup_handler"
825 /* Keyboard interrupt handler. */
827 ctrl_c_handler (DWORD type)
829 static bool saw_close;
831 if (!cygwin_finished_initializing)
833 debug_printf ("exiting with status %p", STATUS_CONTROL_C_EXIT);
834 ExitProcess (STATUS_CONTROL_C_EXIT);
837 _my_tls.remove (INFINITE);
839 /* Return FALSE to prevent an "End task" dialog box from appearing
840 for each Cygwin process window that's open when the computer
841 is shut down or console window is closed. */
843 if (type == CTRL_SHUTDOWN_EVENT)
846 /* Don't send a signal. Only NT service applications and their child
847 processes will receive this event and the services typically already
848 handle the shutdown action when getting the SERVICE_CONTROL_SHUTDOWN
850 sig_send (NULL, SIGTERM);
855 if (myself->ctty != -1)
857 if (type == CTRL_CLOSE_EVENT)
859 sig_send (NULL, SIGHUP);
863 if (!saw_close && type == CTRL_LOGOFF_EVENT)
865 /* Check if the process is actually associated with a visible
866 window station, one which actually represents a visible desktop.
867 If not, the CTRL_LOGOFF_EVENT doesn't concern this process. */
868 if (has_visible_window_station ())
869 sig_send (myself_nowait, SIGHUP);
874 /* If we are a stub and the new process has a pinfo structure, let it
875 handle this signal. */
876 if (dwExeced && pinfo (dwExeced))
879 /* We're only the process group leader when we have a valid pinfo structure.
880 If we don't have one, then the parent "stub" will handle the signal. */
881 if (!pinfo (cygwin_pid (GetCurrentProcessId ())))
884 tty_min *t = cygwin_shared->tty.get_tty (myself->ctty);
885 /* Ignore this if we're not the process group leader since it should be handled
886 *by* the process group leader. */
887 if (myself->ctty != -1 && t->getpgid () == myself->pid &&
888 (GetTickCount () - t->last_ctrl_c) >= MIN_CTRL_C_SLOP)
889 /* Otherwise we just send a SIGINT to the process group and return TRUE (to indicate
890 that we have handled the signal). At this point, type should be
891 a CTRL_C_EVENT or CTRL_BREAK_EVENT. */
893 t->last_ctrl_c = GetTickCount ();
894 killsys (-myself->pid, SIGINT);
895 t->last_ctrl_c = GetTickCount ();
902 /* Function used by low level sig wrappers. */
903 extern "C" void __stdcall
904 set_process_mask (sigset_t newmask)
906 set_signal_mask (newmask);
909 /* Set the signal mask for this process.
910 Note that some signals are unmaskable, as in UNIX. */
911 extern "C" void __stdcall
912 set_signal_mask (sigset_t newmask, sigset_t oldmask)
914 mask_sync->acquire (INFINITE);
915 newmask &= ~SIG_NONMASKABLE;
916 sigset_t mask_bits = oldmask & ~newmask;
917 sigproc_printf ("oldmask %p, newmask %p, mask_bits %p", oldmask, newmask,
919 myself->setsigmask (newmask); // Set a new mask
921 sig_dispatch_pending (true);
923 sigproc_printf ("not calling sig_dispatch_pending");
924 mask_sync->release ();
929 sigpacket::process ()
932 if (si.si_signo != SIGCONT)
933 continue_now = false;
936 continue_now = myself->process_state & PID_STOPPED;
938 myself->process_state &= ~PID_STOPPED;
939 /* Clear pending stop signals */
948 sigproc_printf ("signal %d processing", si.si_signo);
949 struct sigaction thissig = global_sigs[si.si_signo];
951 myself->rusage_self.ru_nsignals++;
953 if (si.si_signo == SIGKILL)
955 if ( si.si_signo == SIGSTOP)
964 insigwait_mask = masked = false;
965 if (special_case = (VFORKPID || ISSTATE (myself, PID_STOPPED)))
967 else if (tls && sigismember (&tls->sigwait_mask, si.si_signo))
968 insigwait_mask = true;
969 else if (!tls && (tls = _cygtls::find_tls (si.si_signo)))
970 insigwait_mask = true;
971 else if (!(masked = sigismember (mask, si.si_signo)) && tls)
972 masked = sigismember (&tls->sigmask, si.si_signo);
975 goto thread_specific;
980 if (special_case || masked)
982 sigproc_printf ("signal %d blocked", si.si_signo);
988 handler = (void *) thissig.sa_handler;
990 /* Clear pending SIGCONT on stop signals */
991 if (si.si_signo == SIGTSTP || si.si_signo == SIGTTIN || si.si_signo == SIGTTOU)
996 __small_sprintf (sigmsg, "cygwin: signal %d\n", si.si_signo);
997 OutputDebugString (sigmsg);
1000 if (handler == (void *) SIG_DFL)
1003 goto thread_specific;
1004 if (si.si_signo == SIGCHLD || si.si_signo == SIGIO || si.si_signo == SIGCONT || si.si_signo == SIGWINCH
1005 || si.si_signo == SIGURG)
1007 sigproc_printf ("default signal %d ignored", si.si_signo);
1009 SetEvent (signal_arrived);
1013 if (si.si_signo == SIGTSTP || si.si_signo == SIGTTIN || si.si_signo == SIGTTOU)
1019 if (handler == (void *) SIG_IGN)
1021 sigproc_printf ("signal %d ignored", si.si_signo);
1025 if (handler == (void *) SIG_ERR)
1031 /* Eat multiple attempts to STOP */
1032 if (ISSTATE (myself, PID_STOPPED))
1034 handler = (void *) sig_handle_tty_stop;
1035 thissig = global_sigs[SIGSTOP];
1039 tls->set_siginfo (this);
1041 /* Dispatch to the appropriate function. */
1042 sigproc_printf ("signal %d, about to call %p", si.si_signo, handler);
1043 rc = setup_handler (si.si_signo, handler, thissig, tls);
1048 sigproc_printf ("returning %d", rc);
1052 tls->sig = si.si_signo;
1053 tls->set_siginfo (this);
1054 sigproc_printf ("releasing sigwait for thread");
1055 SetEvent (tls->event);
1059 if (si.si_signo == SIGQUIT || si.si_signo == SIGABRT)
1062 c.ContextFlags = CONTEXT_FULL;
1063 GetThreadContext (hMainThread, &c);
1064 if (!try_to_debug ())
1065 stackdump (c.Ebp, 1, 1);
1066 si.si_signo |= 0x80;
1068 sigproc_printf ("signal %d, about to call do_exit", si.si_signo);
1069 signal_exit (si.si_signo);
1073 CRITICAL_SECTION NO_COPY exit_lock;
1075 /* Cover function to `do_exit' to handle exiting even in presence of more
1076 exceptions. We used to call exit, but a SIGSEGV shouldn't cause atexit
1079 signal_exit (int rc)
1081 EnterCriticalSection (&exit_lock);
1082 rc = EXIT_SIGNAL | (rc << 8);
1086 /* We'd like to stop the main thread from executing but when we do that it
1087 causes random, inexplicable hangs. So, instead, we set up the priority
1088 of this thread really high so that it should do its thing and then exit. */
1089 (void) SetThreadPriority (hMainThread, THREAD_PRIORITY_IDLE);
1090 (void) SetThreadPriority (GetCurrentThread (), THREAD_PRIORITY_TIME_CRITICAL);
1092 user_data->resourcelocks->Delete ();
1093 user_data->resourcelocks->Init ();
1097 sigproc_printf ("terminating captive process");
1098 TerminateProcess (hExeced, rc);
1101 sigproc_printf ("about to call do_exit (%x)", rc);
1102 (void) SetEvent (signal_arrived);
1106 HANDLE NO_COPY title_mutex = NULL;
1112 char mutex_name[CYG_MAX_PATH];
1113 /* title_mutex protects modification of console title. It's necessary
1114 while finding console window handle */
1116 if (!(title_mutex = CreateMutex (&sec_all_nih, FALSE,
1117 name = shared_name (mutex_name,
1118 "title_mutex", 0))))
1119 api_fatal ("can't create title mutex '%s', %E", name);
1121 ProtectHandle (title_mutex);
1122 new_muto (mask_sync);
1123 windows_system_directory[0] = '\0';
1124 (void) GetSystemDirectory (windows_system_directory, sizeof (windows_system_directory) - 2);
1125 char *end = strchr (windows_system_directory, '\0');
1126 if (end == windows_system_directory)
1127 api_fatal ("can't find windows system directory");
1128 if (end[-1] != '\\')
1133 windows_system_directory_length = end - windows_system_directory;
1134 debug_printf ("windows_system_directory '%s', windows_system_directory_length %d",
1135 windows_system_directory, windows_system_directory_length);
1136 InitializeCriticalSection (&exit_lock);
1140 events_terminate (void)
1146 _cygtls::call_signal_handler ()
1148 int this_sa_flags = 0;
1149 /* Call signal handler. No need to set stacklock since sig effectively
1153 this_sa_flags = sa_flags;
1155 void (*sigfunc) (int) = func;
1158 reset_signal_arrived ();
1159 sigset_t oldmask = oldmask;
1160 int this_errno = saved_errno;
1161 set_process_mask (newmask);
1164 set_process_mask (oldmask);
1165 if (this_errno >= 0)
1166 set_errno (this_errno);
1169 return this_sa_flags & SA_RESTART;
1172 extern "C" void __stdcall
1173 reset_signal_arrived ()
1175 (void) ResetEvent (signal_arrived);
1176 sigproc_printf ("reset signal_arrived");