3 Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
6 This file is part of Cygwin.
8 This software is a copyrighted work licensed under the terms of the
9 Cygwin license. Please consult the file "CYGWIN_LICENSE" for
20 #include "exceptions.h"
26 #include "shared_info.h"
27 #include "perprocess.h"
34 #define CALL_HANDLER_RETRY 20
36 char debugger_command[2 * CYG_MAX_PATH + 20];
39 extern void sigdelayed ();
42 extern NO_COPY DWORD dwExeced;
43 int NO_COPY sigExeced;
45 static BOOL WINAPI ctrl_c_handler (DWORD);
46 static void signal_exit (int) __attribute__ ((noreturn));
47 char windows_system_directory[1024];
48 static size_t windows_system_directory_length;
50 /* This is set to indicate that we have already exited. */
52 static NO_COPY int exit_already = 0;
53 static muto NO_COPY mask_sync;
62 { X (STATUS_ABANDONED_WAIT_0) },
63 { X (STATUS_ACCESS_VIOLATION) },
64 { X (STATUS_ARRAY_BOUNDS_EXCEEDED) },
65 { X (STATUS_BREAKPOINT) },
66 { X (STATUS_CONTROL_C_EXIT) },
67 { X (STATUS_DATATYPE_MISALIGNMENT) },
68 { X (STATUS_FLOAT_DENORMAL_OPERAND) },
69 { X (STATUS_FLOAT_DIVIDE_BY_ZERO) },
70 { X (STATUS_FLOAT_INEXACT_RESULT) },
71 { X (STATUS_FLOAT_INVALID_OPERATION) },
72 { X (STATUS_FLOAT_OVERFLOW) },
73 { X (STATUS_FLOAT_STACK_CHECK) },
74 { X (STATUS_FLOAT_UNDERFLOW) },
75 { X (STATUS_GUARD_PAGE_VIOLATION) },
76 { X (STATUS_ILLEGAL_INSTRUCTION) },
77 { X (STATUS_INTEGER_DIVIDE_BY_ZERO) },
78 { X (STATUS_INTEGER_OVERFLOW) },
79 { X (STATUS_INVALID_DISPOSITION) },
80 { X (STATUS_IN_PAGE_ERROR) },
81 { X (STATUS_NONCONTINUABLE_EXCEPTION) },
82 { X (STATUS_NO_MEMORY) },
83 { X (STATUS_PENDING) },
84 { X (STATUS_PRIVILEGED_INSTRUCTION) },
85 { X (STATUS_SINGLE_STEP) },
86 { X (STATUS_STACK_OVERFLOW) },
87 { X (STATUS_TIMEOUT) },
88 { X (STATUS_USER_APC) },
89 { X (STATUS_WAIT_0) },
94 /* Initialization code. */
97 dummy_ctrl_c_handler (DWORD dwCtrlType)
103 init_console_handler (BOOL install_handler)
106 while (SetConsoleCtrlHandler (ctrl_c_handler, FALSE))
109 res = SetConsoleCtrlHandler (ctrl_c_handler, TRUE);
110 else if (wincap.has_null_console_handler_routine ())
111 res = SetConsoleCtrlHandler (NULL, TRUE);
113 res = SetConsoleCtrlHandler (dummy_ctrl_c_handler, TRUE);
115 system_printf ("SetConsoleCtrlHandler failed, %E");
119 error_start_init (const char *buf)
123 debugger_command[0] = '\0';
127 char pgm[CYG_MAX_PATH];
128 if (!GetModuleFileName (NULL, pgm, CYG_MAX_PATH))
129 strcpy (pgm, "cygwin1.dll");
130 for (char *p = strchr (pgm, '\\'); p; p = strchr (p, '\\'))
133 __small_sprintf (debugger_command, "%s \"%s\"", buf, pgm);
137 open_stackdumpfile ()
139 if (myself->progname[0])
142 /* write to progname.stackdump if possible */
143 if (!myself->progname[0])
145 else if ((p = strrchr (myself->progname, '\\')))
148 p = myself->progname;
149 char corefile[strlen (p) + sizeof (".stackdump")];
150 __small_sprintf (corefile, "%s.stackdump", p);
151 HANDLE h = CreateFile (corefile, GENERIC_WRITE, 0, &sec_none_nih,
152 CREATE_ALWAYS, 0, 0);
153 if (h != INVALID_HANDLE_VALUE)
155 if (!myself->cygstarted)
156 system_printf ("Dumping stack trace to %s", corefile);
158 debug_printf ("Dumping stack trace to %s", corefile);
159 SetStdHandle (STD_ERROR_HANDLE, h);
164 /* Utilities for dumping the stack, etc. */
167 exception (EXCEPTION_RECORD *e, CONTEXT *in)
169 const char *exception_name = NULL;
173 for (int i = 0; status_info[i].name; i++)
175 if (status_info[i].code == e->ExceptionCode)
177 exception_name = status_info[i].name;
184 small_printf ("Exception: %s at eip=%08x\r\n", exception_name, in->Eip);
186 small_printf ("Exception %d at eip=%08x\r\n", e->ExceptionCode, in->Eip);
187 small_printf ("eax=%08x ebx=%08x ecx=%08x edx=%08x esi=%08x edi=%08x\r\n",
188 in->Eax, in->Ebx, in->Ecx, in->Edx, in->Esi, in->Edi);
189 small_printf ("ebp=%08x esp=%08x program=%s, pid %u, thread %s\r\n",
190 in->Ebp, in->Esp, myself->progname, myself->pid, cygthread::name ());
191 small_printf ("cs=%04x ds=%04x es=%04x fs=%04x gs=%04x ss=%04x\r\n",
192 in->SegCs, in->SegDs, in->SegEs, in->SegFs, in->SegGs, in->SegSs);
195 /* A class for manipulating the stack. */
198 int walk (); /* Uses the "old" method */
199 char *next_offset () {return *((char **) sf.AddrFrame.Offset);}
203 STACKFRAME sf; /* For storing the stack information */
204 void init (DWORD, bool, bool); /* Called the first time that stack info is needed */
206 /* Postfix ++ iterates over the stack, returning zero when nothing is left. */
207 int operator ++(int) { return walk (); }
210 /* The number of parameters used in STACKFRAME */
211 #define NPARAMS (sizeof (thestack.sf.Params) / sizeof (thestack.sf.Params[0]))
213 /* This is the main stack frame info for this process. */
214 static NO_COPY stack_info thestack;
216 /* Initialize everything needed to start iterating. */
218 stack_info::init (DWORD ebp, bool wantargs, bool goodframe)
220 # define debp ((DWORD *) ebp)
221 memset (&sf, 0, sizeof (sf));
223 sf.AddrFrame.Offset = ebp;
227 sf.AddrFrame.Offset = (DWORD) &dummy_frame;
229 sf.AddrReturn.Offset = debp[1];
230 sf.AddrFrame.Mode = AddrModeFlat;
235 /* Walk the stack by looking at successive stored 'bp' frames.
236 This is not foolproof. */
241 if ((ebp = (char **) next_offset ()) == NULL)
244 sf.AddrFrame.Offset = (DWORD) ebp;
245 sf.AddrPC.Offset = sf.AddrReturn.Offset;
247 if (!sf.AddrPC.Offset)
248 return 0; /* stack frames are exhausted */
250 /* The return address always follows the stack pointer */
251 sf.AddrReturn.Offset = (DWORD) *++ebp;
254 /* The arguments follow the return address */
255 for (unsigned i = 0; i < NPARAMS; i++)
256 sf.Params[i] = (DWORD) *++ebp;
262 stackdump (DWORD ebp, int open_file, bool isexception)
264 extern unsigned long rlim_core;
266 if (rlim_core == 0UL)
270 open_stackdumpfile ();
274 thestack.init (ebp, 1, !isexception); /* Initialize from the input CONTEXT */
275 small_printf ("Stack trace:\r\nFrame Function Args\r\n");
276 for (i = 0; i < 16 && thestack++; i++)
278 small_printf ("%08x %08x ", thestack.sf.AddrFrame.Offset,
279 thestack.sf.AddrPC.Offset);
280 for (unsigned j = 0; j < NPARAMS; j++)
281 small_printf ("%s%08x", j == 0 ? " (" : ", ", thestack.sf.Params[j]);
282 small_printf (")\r\n");
284 small_printf ("End of stack trace%s\n",
285 i == 16 ? " (more stack frames may be present)" : "");
288 /* Temporary (?) function for external callers to get a stack dump */
293 c.ContextFlags = CONTEXT_FULL;
294 GetThreadContext (GetCurrentThread (), &c);
295 stackdump (c.Ebp, 0, 0);
298 #define TIME_TO_WAIT_FOR_DEBUGGER 10000
301 try_to_debug (bool waitloop)
303 debug_printf ("debugger_command '%s'", debugger_command);
304 if (*debugger_command == '\0')
306 if (being_debugged ())
312 __small_sprintf (strchr (debugger_command, '\0'), " %u", GetCurrentProcessId ());
314 LONG prio = GetThreadPriority (GetCurrentThread ());
315 SetThreadPriority (GetCurrentThread (), THREAD_PRIORITY_HIGHEST);
316 PROCESS_INFORMATION pi = {NULL, 0, 0, 0};
318 STARTUPINFO si = {0, NULL, NULL, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL};
319 si.lpReserved = NULL;
324 /* FIXME: need to know handles of all running threads to
325 suspend_all_threads_except (current_thread_id);
328 /* if any of these mutexes is owned, we will fail to start any cygwin app
329 until trapped app exits */
331 ReleaseMutex (tty_mutex);
333 /* prevent recursive exception handling */
334 char* rawenv = GetEnvironmentStrings () ;
335 for (char* p = rawenv; *p != '\0'; p = strchr (p, '\0') + 1)
337 if (strncmp (p, "CYGWIN=", strlen ("CYGWIN=")) == 0)
339 char* q = strstr (p, "error_start") ;
340 /* replace 'error_start=...' with '_rror_start=...' */
344 SetEnvironmentVariable ("CYGWIN", p + strlen ("CYGWIN=")) ;
350 console_printf ("*** starting debugger for pid %u, tid %u\n",
351 cygwin_pid (GetCurrentProcessId ()), GetCurrentThreadId ());
353 dbg = CreateProcess (NULL,
358 CREATE_NEW_CONSOLE | CREATE_NEW_PROCESS_GROUP,
365 system_printf ("Failed to start debugger, %E");
370 SetThreadPriority (GetCurrentThread (), THREAD_PRIORITY_IDLE);
371 while (!being_debugged ())
372 low_priority_sleep (0);
376 console_printf ("*** continuing pid %u from debugger call (%d)\n",
377 cygwin_pid (GetCurrentProcessId ()), dbg);
379 SetThreadPriority (GetCurrentThread (), prio);
383 extern "C" DWORD __stdcall RtlUnwind (void *, void *, void *, DWORD);
384 static void __stdcall rtl_unwind (exception_list *, PEXCEPTION_RECORD) __attribute__ ((noinline, regparm (3)));
386 rtl_unwind (exception_list *frame, PEXCEPTION_RECORD e)
396 call _RtlUnwind@16 \n\
401 ": : "r" (frame), "r" (e));
404 /* Main exception handler. */
407 _cygtls::handle_exceptions (EXCEPTION_RECORD *e, exception_list *frame, CONTEXT *in, void *)
409 static bool NO_COPY debugging;
410 static int NO_COPY recursed;
411 _cygtls& me = _my_tls;
413 if (debugging && ++debugging < 500000)
415 SetThreadPriority (hMainThread, THREAD_PRIORITY_NORMAL);
419 /* If we've already exited, don't do anything here. Returning 1
420 tells Windows to keep looking for an exception handler. */
421 if (exit_already || e->ExceptionFlags)
425 si.si_code = SI_KERNEL;
426 /* Coerce win32 value to posix value. */
427 switch (e->ExceptionCode)
429 case STATUS_FLOAT_DENORMAL_OPERAND:
430 case STATUS_FLOAT_DIVIDE_BY_ZERO:
431 case STATUS_FLOAT_INVALID_OPERATION:
432 case STATUS_FLOAT_STACK_CHECK:
433 si.si_signo = SIGFPE;
434 si.si_code = FPE_FLTSUB;
436 case STATUS_FLOAT_INEXACT_RESULT:
437 si.si_signo = SIGFPE;
438 si.si_code = FPE_FLTRES;
440 case STATUS_FLOAT_OVERFLOW:
441 si.si_signo = SIGFPE;
442 si.si_code = FPE_FLTOVF;
444 case STATUS_FLOAT_UNDERFLOW:
445 si.si_signo = SIGFPE;
446 si.si_code = FPE_FLTUND;
448 case STATUS_INTEGER_DIVIDE_BY_ZERO:
449 si.si_signo = SIGFPE;
450 si.si_code = FPE_INTDIV;
452 case STATUS_INTEGER_OVERFLOW:
453 si.si_signo = SIGFPE;
454 si.si_code = FPE_INTOVF;
457 case STATUS_ILLEGAL_INSTRUCTION:
458 si.si_signo = SIGILL;
459 si.si_code = ILL_ILLOPC;
462 case STATUS_PRIVILEGED_INSTRUCTION:
463 si.si_signo = SIGILL;
464 si.si_code = ILL_PRVOPC;
467 case STATUS_NONCONTINUABLE_EXCEPTION:
468 si.si_signo = SIGILL;
469 si.si_code = ILL_ILLADR;
473 si.si_signo = SIGALRM;
476 case STATUS_GUARD_PAGE_VIOLATION:
477 si.si_signo = SIGBUS;
478 si.si_code = BUS_OBJERR;
481 case STATUS_ACCESS_VIOLATION:
482 if (mmap_is_attached_page (e->ExceptionInformation[1]))
484 si.si_signo = SIGBUS;
485 si.si_code = BUS_OBJERR;
489 case STATUS_DATATYPE_MISALIGNMENT:
490 case STATUS_ARRAY_BOUNDS_EXCEEDED:
491 case STATUS_IN_PAGE_ERROR:
492 case STATUS_NO_MEMORY:
493 case STATUS_INVALID_DISPOSITION:
494 case STATUS_STACK_OVERFLOW:
495 si.si_signo = SIGSEGV;
496 si.si_code = SEGV_MAPERR;
499 case STATUS_CONTROL_C_EXIT:
500 si.si_signo = SIGINT;
503 case STATUS_INVALID_HANDLE:
504 /* CloseHandle will throw this exception if it is given an
505 invalid handle. We don't care about the exception; we just
506 want CloseHandle to return an error. This can be revisited
507 if gcc ever supports Windows style structured exception
512 /* If we don't recognize the exception, we have to assume that
513 we are doing structured exception handling, and we let
514 something else handle it. */
518 rtl_unwind (frame, e);
520 debug_printf ("In cygwin_except_handler exc %p at %p sp %p", e->ExceptionCode, in->Eip, in->Esp);
521 debug_printf ("In cygwin_except_handler sig %d at %p", si.si_signo, in->Eip);
523 if (global_sigs[si.si_signo].sa_mask & SIGTOMASK (si.si_signo))
524 syscall_printf ("signal %d, masked %p", si.si_signo,
525 global_sigs[si.si_signo].sa_mask);
527 debug_printf ("In cygwin_except_handler calling %p",
528 global_sigs[si.si_signo].sa_handler);
530 DWORD *ebp = (DWORD *) in->Esp;
531 for (DWORD *bpend = (DWORD *) __builtin_frame_address (0); ebp > bpend; ebp--)
532 if (*ebp == in->SegCs && ebp[-1] == in->Eip)
538 if (!me.fault_guarded ()
539 && (!cygwin_finished_initializing
541 || (void *) global_sigs[si.si_signo].sa_handler == (void *) SIG_DFL
542 || (void *) global_sigs[si.si_signo].sa_handler == (void *) SIG_IGN
543 || (void *) global_sigs[si.si_signo].sa_handler == (void *) SIG_ERR))
545 /* Print the exception to the console */
546 if (!myself->cygstarted)
547 for (int i = 0; status_info[i].name; i++)
548 if (status_info[i].code == e->ExceptionCode)
550 system_printf ("Exception: %s", status_info[i].name);
554 /* Another exception could happen while tracing or while exiting.
555 Only do this once. */
557 system_printf ("Error while dumping state (probably corrupted stack)");
560 if (try_to_debug (0))
566 open_stackdumpfile ();
568 stackdump ((DWORD) ebp, 0, 1);
571 signal_exit (0x80 | si.si_signo); // Flag signal + core dump
574 if (me.fault_guarded ())
575 me.return_from_fault ();
577 si.si_addr = (void *) in->Eip;
578 si.si_errno = si.si_pid = si.si_uid = 0;
580 sig_send (NULL, si, &me); // Signal myself
582 e->ExceptionFlags = 0;
586 /* Utilities to call a user supplied exception handler. */
588 #define SIG_NONMASKABLE (SIGTOMASK (SIGKILL) | SIGTOMASK (SIGSTOP))
590 /* Non-raceable sigsuspend
591 * Note: This implementation is based on the Single UNIX Specification
592 * man page. This indicates that sigsuspend always returns -1 and that
593 * attempts to block unblockable signals will be silently ignored.
594 * This is counter to what appears to be documented in some UNIX
595 * man pages, e.g. Linux.
598 handle_sigsuspend (sigset_t tempmask)
600 if (&_my_tls != _main_tls)
602 cancelable_wait (signal_arrived, INFINITE, cw_cancel_self);
606 sigset_t oldmask = myself->getsigmask (); // Remember for restoration
608 set_signal_mask (tempmask, myself->getsigmask ());
609 sigproc_printf ("oldmask %p, newmask %p", oldmask, tempmask);
611 pthread_testcancel ();
612 cancelable_wait (signal_arrived, INFINITE);
614 set_sig_errno (EINTR); // Per POSIX
616 /* A signal dispatch function will have been added to our stack and will
617 be hit eventually. Set the old mask to be restored when the signal
618 handler returns and indicate its presence by modifying deltamask. */
620 _my_tls.deltamask |= SIG_NONMASKABLE;
621 _my_tls.oldmask = oldmask; // Will be restored by signal handler
625 extern DWORD exec_exit; // Possible exit value for exec
629 sig_handle_tty_stop (int sig)
632 /* Silently ignore attempts to suspend if there is no accommodating
633 cygwin parent to deal with this behavior. */
634 if (!myself->cygstarted)
636 myself->process_state &= ~PID_STOPPED;
640 myself->stopsig = sig;
641 myself->alert_parent (sig);
642 sigproc_printf ("process %d stopped by signal %d", myself->pid, sig);
645 w4[1] = signal_arrived;
646 switch (WaitForMultipleObjects (2, w4, TRUE, INFINITE))
649 case WAIT_OBJECT_0 + 1:
650 reset_signal_arrived ();
651 myself->alert_parent (SIGCONT);
654 api_fatal ("WaitSingleObject failed, %E");
662 _cygtls::interrupt_now (CONTEXT *cx, int sig, void *handler,
663 struct sigaction& siga)
667 MEMORY_BASIC_INFORMATION m;
669 memset (&m, 0, sizeof m);
670 if (!VirtualQuery ((LPCVOID) cx->Eip, &m, sizeof m))
671 sigproc_printf ("couldn't get memory info, pc %p, %E", cx->Eip);
673 char *checkdir = (char *) alloca (windows_system_directory_length + 4);
674 memset (checkdir, 0, sizeof (checkdir));
676 # define h ((HMODULE) m.AllocationBase)
677 /* Apparently Windows 95 can sometimes return bogus addresses from
678 GetThreadContext. These resolve to a strange allocation base.
679 These should *never* be treated as interruptible. */
680 if (!h || m.State != MEM_COMMIT)
682 else if (h == user_data->hmodule)
684 else if (!GetModuleFileName (h, checkdir, windows_system_directory_length + 2))
687 res = !strncasematch (windows_system_directory, checkdir,
688 windows_system_directory_length);
689 sigproc_printf ("pc %p, h %p, interruptible %d", cx->Eip, h, res);
692 if (!res || (incyg || spinning || locked ()))
696 push ((__stack_t) cx->Eip);
697 interrupt_setup (sig, handler, siga);
699 SetThreadContext (*this, cx); /* Restart the thread in a new location */
706 _cygtls::interrupt_setup (int sig, void *handler, struct sigaction& siga)
708 push ((__stack_t) sigdelayed);
709 deltamask = siga.sa_mask & ~SIG_NONMASKABLE;
710 sa_flags = siga.sa_flags;
711 func = (void (*) (int)) handler;
712 saved_errno = -1; // Flag: no errno to save
713 if (handler == sig_handle_tty_stop)
716 myself->process_state |= PID_STOPPED;
719 this->sig = sig; // Should always be last thing set to avoid a race
721 /* Clear any waiting threads prior to dispatching to handler function */
722 int res = SetEvent (signal_arrived); // For an EINTR case
723 proc_subproc (PROC_CLEARWAIT, 1);
724 sigproc_printf ("armed signal_arrived %p, sig %d, res %d", signal_arrived,
728 extern "C" void __stdcall
729 set_sig_errno (int e)
731 *_my_tls.errno_addr = e;
732 _my_tls.saved_errno = e;
733 // sigproc_printf ("errno %d", e);
736 static int setup_handler (int, void *, struct sigaction&, _cygtls *tls)
737 __attribute__((regparm(3)));
739 setup_handler (int sig, void *handler, struct sigaction& siga, _cygtls *tls)
742 bool interrupted = false;
746 sigproc_printf ("trying to send sig %d but signal %d already armed",
751 for (int i = 0; i < CALL_HANDLER_RETRY; i++)
756 sigproc_printf ("controlled interrupt. stackptr %p, stack %p, stackptr[-1] %p",
757 tls->stackptr, tls->stack, tls->stackptr[-1]);
758 tls->interrupt_setup (sig, handler, siga);
766 HANDLE hth = (HANDLE) *tls;
768 /* Suspend the thread which will receive the signal.
769 For Windows 95, we also have to ensure that the addresses returned by
770 GetThreadContext are valid.
771 If one of these conditions is not true we loop for a fixed number of times
772 since we don't want to stall the signal handler. FIXME: Will this result in
774 If the thread is already suspended (which can occur when a program has called
775 SuspendThread on itself) then just queue the signal. */
778 sigproc_printf ("suspending mainthread");
780 cx.ContextFlags = CONTEXT_CONTROL | CONTEXT_INTEGER;
781 if (!GetThreadContext (hth, &cx))
782 memset (&cx, 0, sizeof cx);
783 sigproc_printf ("suspending mainthread PC %p", cx.Eip);
785 res = SuspendThread (hth);
786 /* Just set pending if thread is already suspended */
792 cx.ContextFlags = CONTEXT_CONTROL | CONTEXT_INTEGER;
793 if (!GetThreadContext (hth, &cx))
794 system_printf ("couldn't get context of main thread, %E");
796 interrupted = tls->interrupt_now (&cx, sig, handler, siga);
798 res = ResumeThread (hth);
802 sigproc_printf ("couldn't interrupt. trying again.");
803 low_priority_sleep (0);
807 if (interrupted && tls->event)
809 HANDLE h = tls->event;
813 sigproc_printf ("signal %d %sdelivered", sig, interrupted ? "" : "not ");
818 has_visible_window_station ()
824 /* Check if the process is associated with a visible window station.
825 These are processes running on the local desktop as well as processes
826 running in terminal server sessions.
827 Processes running in a service session not explicitely associated
828 with the desktop (using the "Allow service to interact with desktop"
829 property) are running in an invisible window station. */
830 if ((station_hdl = GetProcessWindowStation ())
831 && GetUserObjectInformationA (station_hdl, UOI_FLAGS, &uof,
833 && (uof.dwFlags & WSF_VISIBLE))
838 /* Keyboard interrupt handler. */
840 ctrl_c_handler (DWORD type)
842 static bool saw_close;
844 if (!cygwin_finished_initializing)
846 if (myself->cygstarted) /* Was this process created by a cygwin process? */
847 return TRUE; /* Yes. Let the parent eventually handle CTRL-C issues. */
848 debug_printf ("exiting with status %p", STATUS_CONTROL_C_EXIT);
849 ExitProcess (STATUS_CONTROL_C_EXIT);
852 _my_tls.remove (INFINITE);
855 if (type == CTRL_C_EVENT || type == CTRL_BREAK_EVENT)
856 proc_subproc (PROC_KILLFORKED, 0);
859 /* Return FALSE to prevent an "End task" dialog box from appearing
860 for each Cygwin process window that's open when the computer
861 is shut down or console window is closed. */
863 if (type == CTRL_SHUTDOWN_EVENT)
866 /* Don't send a signal. Only NT service applications and their child
867 processes will receive this event and the services typically already
868 handle the shutdown action when getting the SERVICE_CONTROL_SHUTDOWN
870 sig_send (NULL, SIGTERM);
875 if (myself->ctty != -1)
877 if (type == CTRL_CLOSE_EVENT)
879 sig_send (NULL, SIGHUP);
883 if (!saw_close && type == CTRL_LOGOFF_EVENT)
886 /* CV, 2005-09-08: The CTRL_LOGOFF_EVENT is only send to services.
887 It's send when *any* user logs off. Services generally have
888 a modified console handler which allows services to survive
889 also after a user logged out, even if the service has a console
890 window attached to the visible window station of the user
891 ("Interact with desktop"). The below code contradicts this
892 standard behaviour, so for now, we disable it and just return
893 FALSE to get the default behaviour or the one the application's
894 own console handler (if any) requires.
895 In other words: We never send SIGHUP to services and their
896 child processes on a LOGOFF event. */
898 /* Check if the process is actually associated with a visible
899 window station, one which actually represents a visible desktop.
900 If not, the CTRL_LOGOFF_EVENT doesn't concern this process. */
901 if (has_visible_window_station ())
902 sig_send (myself_nowait, SIGHUP);
908 /* If we are a stub and the new process has a pinfo structure, let it
909 handle this signal. */
910 if (dwExeced && pinfo (dwExeced))
913 /* We're only the process group leader when we have a valid pinfo structure.
914 If we don't have one, then the parent "stub" will handle the signal. */
915 if (!pinfo (cygwin_pid (GetCurrentProcessId ())))
918 tty_min *t = cygwin_shared->tty.get_tty (myself->ctty);
919 /* Ignore this if we're not the process group leader since it should be handled
920 *by* the process group leader. */
921 if (myself->ctty != -1 && t->getpgid () == myself->pid &&
922 (GetTickCount () - t->last_ctrl_c) >= MIN_CTRL_C_SLOP)
923 /* Otherwise we just send a SIGINT to the process group and return TRUE (to indicate
924 that we have handled the signal). At this point, type should be
925 a CTRL_C_EVENT or CTRL_BREAK_EVENT. */
928 /* If intr and quit are both mapped to ^C, send SIGQUIT on ^BREAK */
929 if (type == CTRL_BREAK_EVENT
930 && t->ti.c_cc[VINTR] == 3 && t->ti.c_cc[VQUIT] == 3)
932 t->last_ctrl_c = GetTickCount ();
933 killsys (-myself->pid, sig);
934 t->last_ctrl_c = GetTickCount ();
941 /* Function used by low level sig wrappers. */
942 extern "C" void __stdcall
943 set_process_mask (sigset_t newmask)
945 set_signal_mask (newmask, myself->getsigmask ());
946 sigproc_printf ("mask now %p\n", myself->getsigmask ());
952 /* check that sig is in right range */
953 if (sig < 0 || sig >= NSIG)
956 syscall_printf ("signal %d out of range", sig);
959 mask_sync.acquire (INFINITE);
960 sigset_t mask = myself->getsigmask ();
961 sigaddset (&mask, sig);
962 set_signal_mask (mask, myself->getsigmask ());
963 mask_sync.release ();
970 /* check that sig is in right range */
971 if (sig < 0 || sig >= NSIG)
974 syscall_printf ("signal %d out of range", sig);
977 mask_sync.acquire (INFINITE);
978 sigset_t mask = myself->getsigmask ();
979 sigdelset (&mask, sig);
980 set_signal_mask (mask, myself->getsigmask ());
981 mask_sync.release ();
985 /* Update the signal mask for this process and return the old mask.
986 Called from sigdelayed */
988 set_process_mask_delta ()
990 mask_sync.acquire (INFINITE);
991 sigset_t newmask, oldmask;
993 if (_my_tls.deltamask & SIG_NONMASKABLE)
994 oldmask = _my_tls.oldmask; /* from handle_sigsuspend */
996 oldmask = myself->getsigmask ();
997 newmask = (oldmask | _my_tls.deltamask) & ~SIG_NONMASKABLE;
998 sigproc_printf ("oldmask %p, newmask %p, deltamask %p", oldmask, newmask,
1000 myself->setsigmask (newmask);
1001 mask_sync.release ();
1005 /* Set the signal mask for this process.
1006 Note that some signals are unmaskable, as in UNIX. */
1007 extern "C" void __stdcall
1008 set_signal_mask (sigset_t newmask, sigset_t& oldmask)
1011 if (&_my_tls == _sig_tls)
1012 small_printf ("********* waiting in signal thread\n");
1014 mask_sync.acquire (INFINITE);
1015 newmask &= ~SIG_NONMASKABLE;
1016 sigset_t mask_bits = oldmask & ~newmask;
1017 sigproc_printf ("oldmask %p, newmask %p, mask_bits %p", oldmask, newmask,
1021 sig_dispatch_pending (true);
1023 sigproc_printf ("not calling sig_dispatch_pending");
1024 mask_sync.release ();
1028 sigpacket::process ()
1031 if (si.si_signo != SIGCONT)
1032 continue_now = false;
1035 continue_now = myself->process_state & PID_STOPPED;
1036 myself->stopsig = 0;
1037 myself->process_state &= ~PID_STOPPED;
1038 /* Clear pending stop signals */
1039 sig_clear (SIGSTOP);
1040 sig_clear (SIGTSTP);
1041 sig_clear (SIGTTIN);
1042 sig_clear (SIGTTOU);
1047 sigproc_printf ("signal %d processing", si.si_signo);
1048 struct sigaction thissig = global_sigs[si.si_signo];
1050 myself->rusage_self.ru_nsignals++;
1054 if (!hExeced || (void *) thissig.sa_handler == (void *) SIG_IGN)
1055 handler = (void *) thissig.sa_handler;
1061 if (si.si_signo == SIGKILL)
1063 if (si.si_signo == SIGSTOP)
1065 sig_clear (SIGCONT);
1071 bool insigwait_mask;
1072 if ((masked = ISSTATE (myself, PID_STOPPED)))
1073 insigwait_mask = false;
1075 insigwait_mask = !handler && (tls = _cygtls::find_tls (si.si_signo));
1077 insigwait_mask = sigismember (&tls->sigwait_mask, si.si_signo);
1080 goto thread_specific;
1083 /* nothing to do */;
1084 else if (sigismember (mask, si.si_signo))
1087 masked = sigismember (&tls->sigmask, si.si_signo);
1094 sigproc_printf ("signal %d blocked", si.si_signo);
1099 /* Clear pending SIGCONT on stop signals */
1100 if (si.si_signo == SIGTSTP || si.si_signo == SIGTTIN || si.si_signo == SIGTTOU)
1101 sig_clear (SIGCONT);
1104 if (being_debugged ())
1106 char sigmsg[sizeof (_CYGWIN_SIGNAL_STRING " 0xffffffff")];
1107 __small_sprintf (sigmsg, _CYGWIN_SIGNAL_STRING " %p", si.si_signo);
1108 OutputDebugString (sigmsg);
1112 if (handler == (void *) SIG_DFL)
1115 goto thread_specific;
1116 if (si.si_signo == SIGCHLD || si.si_signo == SIGIO || si.si_signo == SIGCONT || si.si_signo == SIGWINCH
1117 || si.si_signo == SIGURG)
1119 sigproc_printf ("default signal %d ignored", si.si_signo);
1121 SetEvent (signal_arrived);
1125 if (si.si_signo == SIGTSTP || si.si_signo == SIGTTIN || si.si_signo == SIGTTOU)
1131 if (handler == (void *) SIG_IGN)
1133 sigproc_printf ("signal %d ignored", si.si_signo);
1137 if (handler == (void *) SIG_ERR)
1140 tls->set_siginfo (this);
1144 /* Eat multiple attempts to STOP */
1145 if (ISSTATE (myself, PID_STOPPED))
1147 handler = (void *) sig_handle_tty_stop;
1148 thissig = global_sigs[SIGSTOP];
1151 /* Dispatch to the appropriate function. */
1152 sigproc_printf ("signal %d, about to call %p", si.si_signo, handler);
1153 rc = setup_handler (si.si_signo, handler, thissig, tls);
1158 sigproc_printf ("returning %d", rc);
1162 tls->sig = si.si_signo;
1163 tls->set_siginfo (this);
1164 sigproc_printf ("releasing sigwait for thread");
1165 SetEvent (tls->event);
1169 if (si.si_signo == SIGQUIT || si.si_signo == SIGABRT)
1172 c.ContextFlags = CONTEXT_FULL;
1173 GetThreadContext (hMainThread, &c);
1174 if (!try_to_debug ())
1175 stackdump (c.Ebp, 1, 1);
1176 si.si_signo |= 0x80;
1178 sigproc_printf ("signal %d, about to call do_exit", si.si_signo);
1179 signal_exit (si.si_signo); /* never returns */
1182 /* Cover function to `do_exit' to handle exiting even in presence of more
1183 exceptions. We used to call exit, but a SIGSEGV shouldn't cause atexit
1186 signal_exit (int rc)
1190 sigproc_printf ("terminating captive process");
1191 TerminateProcess (hExeced, sigExeced = rc);
1194 lock_process until_exit (true);
1195 if (hExeced || exit_state)
1198 /* Starve other threads in a vain attempt to stop them from doing something
1200 SetThreadPriority (GetCurrentThread (), THREAD_PRIORITY_TIME_CRITICAL);
1202 user_data->resourcelocks->Delete ();
1203 user_data->resourcelocks->Init ();
1205 sigproc_printf ("about to call do_exit (%x)", rc);
1206 SetEvent (signal_arrived);
1210 HANDLE NO_COPY tty_mutex = NULL;
1216 char mutex_name[CYG_MAX_PATH];
1217 /* tty_mutex is on while searching for a tty slot. It's necessary
1218 while finding console window handle */
1220 if (!(tty_mutex = CreateMutex (&sec_all_nih, FALSE,
1221 name = shared_name (mutex_name,
1223 api_fatal ("can't create title mutex '%s', %E", name);
1225 ProtectHandle (tty_mutex);
1226 mask_sync.init ("mask_sync");
1227 windows_system_directory[0] = '\0';
1228 GetSystemDirectory (windows_system_directory, sizeof (windows_system_directory) - 2);
1229 char *end = strchr (windows_system_directory, '\0');
1230 if (end == windows_system_directory)
1231 api_fatal ("can't find windows system directory");
1232 if (end[-1] != '\\')
1237 windows_system_directory_length = end - windows_system_directory;
1238 debug_printf ("windows_system_directory '%s', windows_system_directory_length %d",
1239 windows_system_directory, windows_system_directory_length);
1249 _cygtls::call_signal_handler ()
1251 int this_sa_flags = 0;
1252 /* Call signal handler. */
1256 this_sa_flags = sa_flags;
1260 reset_signal_arrived ();
1261 sigset_t this_oldmask = set_process_mask_delta ();
1262 int this_errno = saved_errno;
1264 unlock (); // make sure synchronized
1266 if (!(this_sa_flags & SA_SIGINFO))
1268 void (*sigfunc) (int) = func;
1273 siginfo_t thissi = infodata;
1274 void (*sigact) (int, siginfo_t *, void *) = (void (*) (int, siginfo_t *, void *)) func;
1275 /* no ucontext_t information provided yet */
1276 sigact (thissig, &thissi, NULL);
1279 set_signal_mask (this_oldmask, myself->getsigmask ());
1280 if (this_errno >= 0)
1281 set_errno (this_errno);
1284 return this_sa_flags & SA_RESTART;
1287 extern "C" void __stdcall
1288 reset_signal_arrived ()
1290 // NEEDED? WaitForSingleObject (signal_arrived, 10);
1291 ResetEvent (signal_arrived);
1292 sigproc_printf ("reset signal_arrived");
1293 if (_my_tls.stackptr > _my_tls.stack)
1294 debug_printf ("stackptr[-1] %p", _my_tls.stackptr[-1]);