3 Copyright 1996, 1997, 1998, 1999, 2000 Cygnus Solutions.
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
16 #include "exceptions.h"
17 #undef DECLSPEC_IMPORT
18 #define DECLSPEC_IMPORT
23 char debugger_command[2 * MAX_PATH + 20];
26 static int handle_exceptions (EXCEPTION_RECORD *, void *, CONTEXT *, void *);
27 extern void sigreturn ();
28 extern void sigdelayed ();
29 extern void siglast ();
30 extern DWORD __sigfirst, __siglast;
33 static BOOL WINAPI ctrl_c_handler (DWORD);
34 static void really_exit (int);
35 static char windows_system_directory[1024];
36 static size_t windows_system_directory_length;
38 /* This is set to indicate that we have already exited. */
40 static NO_COPY int exit_already = 0;
41 static NO_COPY muto *mask_sync = NULL;
43 HMODULE cygwin_hmodule;
44 HANDLE NO_COPY console_handler_thread_waiter = NULL;
50 } status_info[] NO_COPY =
53 { X (STATUS_ABANDONED_WAIT_0) },
54 { X (STATUS_ACCESS_VIOLATION) },
55 { X (STATUS_ARRAY_BOUNDS_EXCEEDED) },
56 { X (STATUS_BREAKPOINT) },
57 { X (STATUS_CONTROL_C_EXIT) },
58 { X (STATUS_DATATYPE_MISALIGNMENT) },
59 { X (STATUS_FLOAT_DENORMAL_OPERAND) },
60 { X (STATUS_FLOAT_DIVIDE_BY_ZERO) },
61 { X (STATUS_FLOAT_INEXACT_RESULT) },
62 { X (STATUS_FLOAT_INVALID_OPERATION) },
63 { X (STATUS_FLOAT_OVERFLOW) },
64 { X (STATUS_FLOAT_STACK_CHECK) },
65 { X (STATUS_FLOAT_UNDERFLOW) },
66 { X (STATUS_GUARD_PAGE_VIOLATION) },
67 { X (STATUS_ILLEGAL_INSTRUCTION) },
68 { X (STATUS_INTEGER_DIVIDE_BY_ZERO) },
69 { X (STATUS_INTEGER_OVERFLOW) },
70 { X (STATUS_INVALID_DISPOSITION) },
71 { X (STATUS_IN_PAGE_ERROR) },
72 { X (STATUS_NONCONTINUABLE_EXCEPTION) },
73 { X (STATUS_NO_MEMORY) },
74 { X (STATUS_PENDING) },
75 { X (STATUS_PRIVILEGED_INSTRUCTION) },
76 { X (STATUS_SINGLE_STEP) },
77 { X (STATUS_STACK_OVERFLOW) },
78 { X (STATUS_TIMEOUT) },
79 { X (STATUS_USER_APC) },
80 { X (STATUS_WAIT_0) },
85 /* Initialization code. */
89 // Set up the exception handler for the current thread. The PowerPC & Mips
90 // use compiler generated tables to set up the exception handlers for each
91 // region of code, and the kernel walks the call list until it finds a region
92 // of code that handles exceptions. The x86 on the other hand uses segment
93 // register fs, offset 0 to point to the current exception handler.
95 asm (".equ __except_list,0");
97 extern exception_list *_except_list asm ("%fs:__except_list");
100 init_exception_handler (exception_list *el)
102 el->handler = handle_exceptions;
103 el->prev = _except_list;
107 #define INIT_EXCEPTION_HANDLER(el) init_exception_handler (el)
111 set_console_handler ()
113 /* Initialize global security attribute stuff */
115 sec_none.nLength = sec_none_nih.nLength =
116 sec_all.nLength = sec_all_nih.nLength = sizeof (SECURITY_ATTRIBUTES);
117 sec_none.bInheritHandle = sec_all.bInheritHandle = TRUE;
118 sec_none_nih.bInheritHandle = sec_all_nih.bInheritHandle = FALSE;
119 sec_none.lpSecurityDescriptor = sec_none_nih.lpSecurityDescriptor = NULL;
120 sec_all.lpSecurityDescriptor = sec_all_nih.lpSecurityDescriptor =
123 /* Allocate the event needed for ctrl_c_handler synchronization with
125 if (!console_handler_thread_waiter)
126 CreateEvent (&sec_none_nih, TRUE, TRUE, NULL);
127 (void) SetConsoleCtrlHandler (ctrl_c_handler, FALSE);
128 if (!SetConsoleCtrlHandler (ctrl_c_handler, TRUE))
129 system_printf ("SetConsoleCtrlHandler failed, %E");
133 init_exceptions (exception_list *el)
135 #ifdef INIT_EXCEPTION_HANDLER
136 INIT_EXCEPTION_HANDLER (el);
141 error_start_init (const char *buf)
145 debugger_command[0] = '\0';
149 char myself_posix_name[MAX_PATH];
151 /* FIXME: gdb cannot use win32 paths, but what if debugger isn't gdb? */
152 cygwin_conv_to_posix_path (myself->progname, myself_posix_name);
153 __small_sprintf (debugger_command, "%s %s", buf, myself_posix_name);
156 /* Utilities for dumping the stack, etc. */
159 exception (EXCEPTION_RECORD *e, CONTEXT *in)
161 const char *exception_name = 0;
165 for (int i = 0; status_info[i].name; i++)
167 if (status_info[i].code == e->ExceptionCode)
169 exception_name = status_info[i].name;
178 small_printf ("Exception: %s at eip=%08x\r\n", exception_name, in->Eip);
180 small_printf ("Exception %d at eip=%08x\r\n", e->ExceptionCode, in->Eip);
181 small_printf ("eax=%08x ebx=%08x ecx=%08x edx=%08x esi=%08x edi=%08x\r\n",
182 in->Eax, in->Ebx, in->Ecx, in->Edx, in->Esi, in->Edi);
183 small_printf ("ebp=%08x esp=%08x program=%s\r\n",
184 in->Ebp, in->Esp, myself->progname);
185 small_printf ("cs=%04x ds=%04x es=%04x fs=%04x gs=%04x ss=%04x\r\n",
186 in->SegCs, in->SegDs, in->SegEs, in->SegFs, in->SegGs, in->SegSs);
190 system_printf ("Had an exception");
195 static LPVOID __stdcall
201 static DWORD __stdcall
208 /* Print a stack backtrace. */
210 #define HAVE_STACK_TRACE
212 /* Set from CYGWIN environment variable if want to use old method. */
213 BOOL NO_COPY oldstack = 0;
215 /* The function used to load the imagehlp DLL. Returns TRUE if the
217 static LoadDLLinitfunc (imagehlp)
219 imagehlp_handle = LoadLibrary ("imagehlp.dll");
220 return !!imagehlp_handle;
223 LoadDLLinit (imagehlp) /* Set up storage for imagehlp.dll autoload */
224 LoadDLLfunc (StackWalk, StackWalk@36, imagehlp)
226 /* A class for manipulating the stack. */
229 int first_time; /* True if just starting to iterate. */
230 HANDLE hproc; /* Handle of process to inspect. */
231 HANDLE hthread; /* Handle of thread to inspect. */
232 int (stack_info::*get) (HANDLE, HANDLE); /* Gets the next stack frame */
234 STACKFRAME sf; /* For storing the stack information */
235 int walk (HANDLE, HANDLE); /* Uses the StackWalk function */
236 int brute_force (HANDLE, HANDLE); /* Uses the "old" method */
237 void init (CONTEXT *); /* Called the first time that stack info is needed */
239 /* The constructor remembers hproc and hthread and determines which stack walking
241 stack_info (int use_old_stack, HANDLE hp, HANDLE ht): hproc(hp), hthread(ht)
243 if (!use_old_stack && LoadDLLinitnow (imagehlp))
244 get = &stack_info::walk;
246 get = &stack_info::brute_force;
248 /* Postfix ++ iterates over the stack, returning zero when nothing is left. */
249 int operator ++(int) { return (this->*get) (hproc, hthread); }
252 /* The number of parameters used in STACKFRAME */
253 #define NPARAMS (sizeof(thestack->sf.Params) / sizeof(thestack->sf.Params[0]))
255 /* This is the main stack frame info for this process. */
256 static stack_info *thestack = NULL;
257 static signal_dispatch sigsave;
259 /* Initialize everything needed to start iterating. */
261 stack_info::init (CONTEXT *cx)
264 memset (&sf, 0, sizeof(sf));
265 sf.AddrPC.Offset = cx->Eip;
266 sf.AddrPC.Mode = AddrModeFlat;
267 sf.AddrStack.Offset = cx->Esp;
268 sf.AddrStack.Mode = AddrModeFlat;
269 sf.AddrFrame.Offset = cx->Ebp;
270 sf.AddrFrame.Mode = AddrModeFlat;
273 /* Walk the stack by looking at successive stored 'bp' frames.
274 This is not foolproof. */
276 stack_info::brute_force (HANDLE, HANDLE)
280 /* Everything is filled out already */
281 ebp = (char **) sf.AddrFrame.Offset;
282 else if ((ebp = (char **) *(char **) sf.AddrFrame.Offset) != NULL)
284 sf.AddrFrame.Offset = (DWORD) ebp;
285 sf.AddrPC.Offset = sf.AddrReturn.Offset;
291 if (!sf.AddrPC.Offset)
292 return 0; /* stack frames are exhausted */
294 /* The return address always follows the stack pointer */
295 sf.AddrReturn.Offset = (DWORD) *++ebp;
297 /* The arguments follow the return address */
298 for (unsigned i = 0; i < NPARAMS; i++)
299 sf.Params[i] = (DWORD) *++ebp;
303 /* Use Win32 StackWalk() API to display the stack. This is theoretically
304 more foolproof than the brute force method above. */
306 stack_info::walk (HANDLE hproc, HANDLE hthread)
309 /* It would be nice to get more information (like DLL symbols and module name)
310 for each stack frame but in order to do that we have to call SymInitialize.
311 It doesn't seem to be possible to do this inside of an excaption handler for
313 static int initialized = 0;
314 if (!initialized && !SymInitialize(hproc, NULL, TRUE))
315 small_printf("SymInitialize error, %E\n");
319 return StackWalk (IMAGE_FILE_MACHINE_I386, hproc, hthread, &sf, NULL, NULL,
320 sfta, sgmb, NULL) && !!sf.AddrFrame.Offset;
323 /* Dump the stack using either the old method or the new Win32 API method */
325 stack (HANDLE hproc, HANDLE hthread, CONTEXT *cx)
329 /* Set this up if it's the first time. */
331 thestack = new stack_info (oldstack, hproc, hthread);
333 thestack->init (cx); /* Initialize from the input CONTEXT */
334 small_printf ("Stack trace:\r\nFrame Function Args\r\n");
335 for (i = 0; i < 16 && (*thestack)++ ; i++)
337 small_printf ("%08x %08x ", thestack->sf.AddrFrame.Offset,
338 thestack->sf.AddrPC.Offset);
339 for (unsigned j = 0; j < NPARAMS; j++)
340 small_printf ("%s%08x", j == 0 ? " (" : ", ", thestack->sf.Params[j]);
341 small_printf (")\r\n");
343 small_printf ("End of stack trace%s",
344 i == 16 ? " (more stack frames may be present)" : "");
347 /* Temporary (?) function for external callers to get a stack dump */
352 c.ContextFlags = CONTEXT_FULL;
353 HANDLE h1 = GetCurrentProcess ();
354 HANDLE h2 = GetCurrentThread ();
355 GetThreadContext (h2, &c);
359 static int NO_COPY keep_looping = 0;
364 debug_printf ("debugger_command %s", debugger_command);
365 if (*debugger_command == '\0')
368 __small_sprintf (strchr (debugger_command, '\0'), " %u", GetCurrentProcessId ());
372 PROCESS_INFORMATION pi = {NULL, 0, 0, 0};
374 STARTUPINFO si = {0, NULL, NULL, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL};
375 si.lpReserved = NULL;
380 /* FIXME: need to know handles of all running threads to
381 suspend_all_threads_except (current_thread_id);
384 /* if any of these mutexes is owned, we will fail to start any cygwin app
385 until trapped app exits */
387 ReleaseMutex (pinfo_mutex);
388 ReleaseMutex (title_mutex);
390 dbg = CreateProcess (NULL,
395 CREATE_NEW_CONSOLE | CREATE_NEW_PROCESS_GROUP,
402 system_printf ("Failed to start debugger: %E");
403 /* FIXME: need to know handles of all running threads to
404 resume_all_threads_except (current_thread_id);
418 stackdump (HANDLE hproc, HANDLE hthread, EXCEPTION_RECORD *e, CONTEXT *in)
421 if (myself->progname[0])
423 /* write to progname.stackdump if possible */
424 if ((p = strrchr (myself->progname, '\\')))
427 p = myself->progname;
428 char corefile[strlen(p) + sizeof(".stackdump")];
429 __small_sprintf (corefile, "%s.stackdump", p);
430 HANDLE h = CreateFile (corefile, GENERIC_WRITE, 0, &sec_none_nih,
431 CREATE_ALWAYS, 0, 0);
432 if (h != INVALID_HANDLE_VALUE)
434 system_printf ("Dumping stack trace to %s", corefile);
435 SetStdHandle (STD_ERROR_HANDLE, h);
440 stack (hproc, hthread, in);
443 /* Main exception handler. */
446 handle_exceptions (EXCEPTION_RECORD *e, void *, CONTEXT *in, void *)
450 /* If we've already exited, don't do anything here. Returning 1
451 tells Windows to keep looking for an exception handler. */
455 /* Coerce win32 value to posix value. */
456 switch (e->ExceptionCode)
458 case STATUS_FLOAT_DENORMAL_OPERAND:
459 case STATUS_FLOAT_DIVIDE_BY_ZERO:
460 case STATUS_FLOAT_INEXACT_RESULT:
461 case STATUS_FLOAT_INVALID_OPERATION:
462 case STATUS_FLOAT_OVERFLOW:
463 case STATUS_FLOAT_STACK_CHECK:
464 case STATUS_FLOAT_UNDERFLOW:
465 case STATUS_INTEGER_DIVIDE_BY_ZERO:
466 case STATUS_INTEGER_OVERFLOW:
470 case STATUS_ILLEGAL_INSTRUCTION:
471 case STATUS_PRIVILEGED_INSTRUCTION:
472 case STATUS_NONCONTINUABLE_EXCEPTION:
480 case STATUS_ACCESS_VIOLATION:
481 case STATUS_DATATYPE_MISALIGNMENT:
482 case STATUS_ARRAY_BOUNDS_EXCEEDED:
483 case STATUS_GUARD_PAGE_VIOLATION:
484 case STATUS_IN_PAGE_ERROR:
485 case STATUS_NO_MEMORY:
486 case STATUS_INVALID_DISPOSITION:
487 case STATUS_STACK_OVERFLOW:
491 case STATUS_CONTROL_C_EXIT:
495 case STATUS_INVALID_HANDLE:
496 /* CloseHandle will throw this exception if it is given an
497 invalid handle. We don't care about the exception; we just
498 want CloseHandle to return an error. This can be revisited
499 if gcc ever supports Windows style structured exception
504 /* If we don't recognize the exception, we have to assume that
505 we are doing structured exception handling, and we let
506 something else handle it. */
510 debug_printf ("In cygwin_except_handler exc %p at %p sp %p", e->ExceptionCode, in->Eip, in->Esp);
511 debug_printf ("In cygwin_except_handler sig = %d at %p", sig, in->Eip);
513 if (myself->getsig(sig).sa_mask & SIGTOMASK (sig))
514 syscall_printf ("signal %d, masked %p", sig, myself->getsig(sig).sa_mask);
516 if (!myself->progname[0]
517 || (void *) myself->getsig(sig).sa_handler == (void *) SIG_DFL
518 || (void *) myself->getsig(sig).sa_handler == (void *) SIG_IGN
519 || (void *) myself->getsig(sig).sa_handler == (void *) SIG_ERR)
521 static NO_COPY int traced = 0;
523 /* Print the exception to the console */
526 for (int i = 0; status_info[i].name; i++)
528 if (status_info[i].code == e->ExceptionCode)
530 system_printf ("Exception: %s", status_info[i].name);
536 /* Another exception could happen while tracing or while exiting.
537 Only do this once. */
539 system_printf ("Error while dumping state (probably corrupted stack)");
543 DuplicateHandle (hMainProc, GetCurrentThread (),
544 hMainProc, &hthread, 0, FALSE, DUPLICATE_SAME_ACCESS);
545 stackdump (hMainProc, hthread, e, in);
548 really_exit (EXIT_SIGNAL | sig);
551 debug_printf ("In cygwin_except_handler calling %p",
552 myself->getsig(sig).sa_handler);
554 DWORD *bp = (DWORD *)in->Esp;
555 for (DWORD *bpend = bp - 8; bp > bpend; bp--)
556 if (*bp == in->SegCs && bp[-1] == in->Eip)
562 in->Ebp = (DWORD) bp;
564 sig_send (NULL, sig); // Signal myself
568 #endif /* __i386__ */
570 #ifndef HAVE_STACK_TRACE
574 system_printf ("Stack trace not yet supported on this machine.");
579 /* Utilities to call a user supplied exception handler. */
581 #define SIG_NONMASKABLE (SIGTOMASK (SIGCONT) | SIGTOMASK (SIGKILL) | SIGTOMASK (SIGSTOP))
584 #define HAVE_CALL_HANDLER
586 /* Non-raceable sigsuspend
587 * Note: This implementation is based on the Single UNIX Specification
588 * man page. This indicates that sigsuspend always returns -1 and that
589 * attempts to block unblockable signals will be silently ignored.
590 * This is counter to what appears to be documented in some UNIX
591 * man pages, e.g. Linux.
594 handle_sigsuspend (sigset_t tempmask)
596 sigset_t oldmask = myself->getsigmask (); // Remember for restoration
598 set_process_mask (tempmask & ~SIG_NONMASKABLE);// Let signals we're
599 // interested in through.
600 sigproc_printf ("old mask %x, new mask %x", oldmask, tempmask);
602 WaitForSingleObject (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 sigsave.oldmask = oldmask; // Will be restored by signal handler
614 extern DWORD exec_exit; // Possible exit value for exec
615 extern int pending_signals;
618 interruptible (DWORD pc)
621 DWORD pchigh = pc & 0xf0000000;
622 return ((pc >= (DWORD) &__sigfirst) && (pc <= (DWORD) &__siglast)) ||
623 !(pchigh == 0xb0000000 || pchigh == 0x70000000 || pchigh == 0x60000000);
626 if ((pc >= (DWORD) &__sigfirst) && (pc <= (DWORD) &__siglast))
630 MEMORY_BASIC_INFORMATION m;
631 memset (&m, 0, sizeof m);
632 if (!VirtualQuery ((LPCVOID) pc, &m, sizeof m))
633 sigproc_printf ("couldn't get memory info, %E");
635 char *checkdir = (char *) alloca (windows_system_directory_length);
636 # define h ((HMODULE) m.AllocationBase)
637 if (h == cygwin_hmodule)
639 else if (!GetModuleFileName (h, checkdir, windows_system_directory_length))
642 res = !strncasematch (windows_system_directory, checkdir,
643 windows_system_directory_length);
646 sigproc_printf ("interruptible %d", res);
652 static void __stdcall
653 interrupt_setup (int sig, struct sigaction& siga, void *handler, DWORD retaddr)
655 sigsave.retaddr = retaddr;
656 sigsave.oldmask = myself->getsigmask (); // Remember for restoration
657 /* FIXME: Not multi-thread aware */
658 set_process_mask (myself->getsigmask () | siga.sa_mask | SIGTOMASK (sig));
659 sigsave.func = (void (*)(int)) handler;
661 sigsave.saved_errno = -1; // Flag: no errno to save
665 interrupt_now (CONTEXT *ctx, int sig, struct sigaction& siga, void *handler)
667 interrupt_setup (sig, siga, handler, ctx->Eip);
668 ctx->Eip = (DWORD) sigdelayed;
669 SetThreadContext (myself->getthread2signal(), ctx); /* Restart the thread */
673 interrupt_on_return (CONTEXT *ctx, int sig, struct sigaction& siga, void *handler)
678 return 0; /* Already have a signal stacked up */
680 /* Set this up if it's the first time. */
681 /* FIXME: Eventually augment to handle more than one thread */
683 thestack = new stack_info (oldstack, hMainProc, hMainThread);
685 thestack->init (ctx); /* Initialize from the input CONTEXT */
686 for (i = 0; i < 32 && (*thestack)++ ; i++)
687 if (interruptible (thestack->sf.AddrReturn.Offset))
689 DWORD *addr_retaddr = ((DWORD *)thestack->sf.AddrFrame.Offset) + 1;
690 if (*addr_retaddr == thestack->sf.AddrReturn.Offset)
692 interrupt_setup (sig, siga, handler, *addr_retaddr);
693 *addr_retaddr = (DWORD) sigdelayed;
701 extern "C" void __stdcall
702 set_sig_errno (int e)
705 sigsave.saved_errno = e;
706 debug_printf ("errno %d", e);
710 call_handler (int sig, struct sigaction& siga, void *handler)
717 if (hExeced != NULL && hExeced != INVALID_HANDLE_VALUE)
719 SetEvent (signal_arrived); // For an EINTR case
720 sigproc_printf ("armed signal_arrived");
721 exec_exit = sig; // Maybe we'll exit with this value
724 hth = myself->getthread2signal ();
726 /* Suspend the thread which will receive the signal. But first ensure that
727 this thread doesn't have the sync_proc_subproc and mask_sync mutos, since
728 we need those (hack alert). If the thread-to-be-suspended has either of
729 these mutos, enter a busy loop until it is released. If the thread is
730 already suspended (which should never occur) then just queue the signal. */
733 sigproc_printf ("suspending mainthread");
734 res = SuspendThread (hth);
736 /* FIXME: Make multi-thread aware */
737 for (muto *m = muto_start.next; m != NULL; m = m->next)
738 if (m->unstable () || m->owner () == maintid)
744 sigproc_printf ("suspended thread owns a muto");
752 sigproc_printf ("SuspendThread returned %d", res);
762 /* FIXME - this does not preserve FPU state */
763 orig.ContextFlags = CONTEXT_CONTROL | CONTEXT_INTEGER;
764 if (!GetThreadContext (hth, cx))
766 system_printf ("couldn't get context of main thread, %E");
771 if (cx == &orig && interruptible (cx->Eip))
772 interrupt_now (cx, sig, siga, handler);
773 else if (!interrupt_on_return (cx, sig, siga, handler))
776 pending_signals = 1; /* FIXME: Probably need to be more tricky here */
777 sig_set_pending (sig);
783 (void) SetEvent (signal_arrived); // For an EINTR case
784 sigproc_printf ("armed signal_arrived %p, res %d", signal_arrived, res);
785 /* Clear any waiting threads prior to dispatching to handler function */
786 proc_subproc(PROC_CLEARWAIT, 1);
790 res = ResumeThread (hth);
791 sigproc_printf ("ResumeThread returned %d", res);
794 sigproc_printf ("returning %d", interrupted);
799 #ifndef HAVE_CALL_HANDLER
800 #error "Need to supply machine dependent call_handler"
803 /* Keyboard interrupt handler. */
805 ctrl_c_handler (DWORD type)
807 if (type == CTRL_LOGOFF_EVENT)
810 /* Wait for sigproc_init to tell us that it's safe to send something.
811 This event will always be in a signalled state when wait_sig is
812 ready to process signals. */
813 (void) WaitForSingleObject (console_handler_thread_waiter, 5000);
815 if ((type == CTRL_CLOSE_EVENT) || (type == CTRL_SHUTDOWN_EVENT))
816 /* Return FALSE to prevent an "End task" dialog box from appearing
817 for each Cygwin process window that's open when the computer
818 is shut down or console window is closed. */
820 sig_send (NULL, SIGHUP);
823 tty_min *t = cygwin_shared->tty.get_tty(myself->ctty);
824 /* Ignore this if we're not the process group lead since it should be handled
825 *by* the process group leader. */
826 if (t->getpgid () != myself->pid ||
827 (GetTickCount () - t->last_ctrl_c) < MIN_CTRL_C_SLOP)
830 /* Otherwise we just send a SIGINT to the process group and return TRUE (to indicate
831 that we have handled the signal). At this point, type should be
832 a CTRL_C_EVENT or CTRL_BREAK_EVENT. */
834 t->last_ctrl_c = GetTickCount ();
835 kill (-myself->pid, SIGINT);
836 t->last_ctrl_c = GetTickCount ();
841 /* Set the signal mask for this process.
842 * Note that some signals are unmaskable, as in UNIX.
844 extern "C" void __stdcall
845 set_process_mask (sigset_t newmask)
849 mask_sync->acquire (INFINITE);
850 sigset_t oldmask = myself->getsigmask ();
851 newmask &= ~SIG_NONMASKABLE;
852 sigproc_printf ("old mask = %x, new mask = %x", myself->getsigmask (), newmask);
853 myself->setsigmask (newmask); // Set a new mask
854 mask_sync->release ();
855 if (oldmask != newmask && GetCurrentThreadId () != sigtid)
856 sig_dispatch_pending ();
862 sig_handle_tty_stop (int sig)
867 /* Be sure that process's main thread isn't an owner of vital
868 mutex to prevent cygwin subsystem lockups */
869 waitbuf[0] = pinfo_mutex;
870 waitbuf[1] = title_mutex;
871 WaitForMultipleObjects (2, waitbuf, TRUE, INFINITE);
872 ReleaseMutex (pinfo_mutex);
873 ReleaseMutex (title_mutex);
875 myself->stopsig = sig;
876 myself->process_state |= PID_STOPPED;
877 /* See if we have a living parent. If so, send it a special signal.
878 * It will figure out exactly which pid has stopped by scanning
879 * its list of subprocesses.
881 if (my_parent_is_alive ())
883 pinfo *parent = procinfo(myself->ppid);
884 sig_send (parent, __SIGCHILDSTOPPED);
886 sigproc_printf ("process %d stopped by signal %d, parent_alive %p",
887 myself->pid, sig, parent_alive);
888 /* There is a small race here with the above two mutexes */
889 SuspendThread (hMainThread);
899 sigproc_printf ("signal %d", sig);
901 struct sigaction thissig = myself->getsig(sig);
902 void *handler = (void *) thissig.sa_handler;
904 myself->rusage_self.ru_nsignals++;
906 /* Clear pending SIGCONT on stop signals */
907 if (sig == SIGSTOP || sig == SIGTSTP || sig == SIGTTIN || sig == SIGTTOU)
916 /* FIXME: Should we still do this if SIGCONT has a handler? */
920 myself->process_state &= ~PID_STOPPED;
921 /* Clear pending stop signals */
926 /* Windows 95 hangs on resuming non-suspended thread */
927 SuspendThread (hMainThread);
928 while (ResumeThread (hMainThread) > 1)
930 /* process pending signals */
931 sig_dispatch_pending ();
936 __small_sprintf (sigmsg, "cygwin: signal %d\n", sig);
937 OutputDebugString (sigmsg);
940 if (handler == (void *) SIG_DFL)
942 if (sig == SIGCHLD || sig == SIGIO || sig == SIGCONT || sig == SIGWINCH)
944 sigproc_printf ("default signal %d ignored", sig);
948 if (sig == SIGTSTP || sig == SIGTTIN || sig == SIGTTOU)
954 if (handler == (void *) SIG_IGN)
956 sigproc_printf ("signal %d ignored", sig);
960 if (handler == (void *) SIG_ERR)
963 if ((sig == SIGCHLD) && (thissig.sa_flags & SA_NOCLDSTOP))
969 handler = (void *) sig_handle_tty_stop;
972 /* Dispatch to the appropriate function. */
973 sigproc_printf ("signal %d, about to call %p", sig, thissig.sa_handler);
974 rc = call_handler (sig, thissig, handler);
977 sigproc_printf ("returning %d", rc);
981 if (sig == SIGQUIT || sig == SIGABRT)
983 stackdump (NULL, NULL, NULL, NULL);
986 sigproc_printf ("signal %d, about to call do_exit", sig);
987 TerminateThread (hMainThread, 0);
988 /* FIXME: This just works around the problem so that we don't attempt to
989 use a resource lock when exiting. */
990 user_data->resourcelocks->Delete();
991 user_data->resourcelocks->Init();
992 do_exit (EXIT_SIGNAL | (sig << 8));
996 /* Cover function to `do_exit' to handle exiting even in presence of more
997 exceptions. We use to call exit, but a SIGSEGV shouldn't cause atexit
1001 really_exit (int rc)
1003 /* If the exception handler gets a trap, we could recurse awhile.
1004 If this is non-zero, skip the cleaning up and exit NOW. */
1008 /* We are going down - reset our process_state without locking. */
1009 myself->record_death (FALSE);
1016 HANDLE NO_COPY pinfo_mutex = NULL;
1017 HANDLE NO_COPY title_mutex = NULL;
1022 /* pinfo_mutex protects access to process table */
1024 if (!(pinfo_mutex = CreateMutex (&sec_all_nih, FALSE,
1025 shared_name ("pinfo_mutex", 0))))
1026 api_fatal ("catastrophic failure - unable to create pinfo_mutex, %E");
1028 ProtectHandle (pinfo_mutex);
1030 /* title_mutex protects modification of console title. It's neccessary
1031 while finding console window handle */
1033 if (!(title_mutex = CreateMutex (&sec_all_nih, FALSE,
1034 shared_name ("title_mutex", 0))))
1035 api_fatal ("can't create title mutex, %E");
1037 ProtectHandle (title_mutex);
1038 mask_sync = new_muto (FALSE, NULL);
1039 windows_system_directory[0] = '\0';
1040 (void) GetSystemDirectory (windows_system_directory, sizeof (windows_system_directory) - 2);
1041 char *end = strchr (windows_system_directory, '\0');
1042 if (end == windows_system_directory)
1043 api_fatal ("can't find windows system directory");
1044 if (end[-1] != '\\')
1049 windows_system_directory_length = end - windows_system_directory;
1050 debug_printf ("windows_system_directory '%s', windows_system_directory_length %d",
1051 windows_system_directory, windows_system_directory_length);
1052 debug_printf ("cygwin_hmodule %p", cygwin_hmodule);
1056 events_terminate (void)
1058 //CloseHandle (pinfo_mutex); // Use implicit close on exit to avoid race
1059 ForceCloseHandle (title_mutex);
1063 #define pid_offset (unsigned)(((pinfo *)NULL)->pid)
1065 static void __stdcall
1066 reset_signal_arrived () __attribute__ ((unused));
1067 static void __stdcall
1068 reset_signal_arrived ()
1070 (void) ResetEvent (signal_arrived);
1071 sigproc_printf ("reset signal_arrived");
1074 void unused_sig_wrapper()
1076 /* Signal cleanup stuff. Cleans up stack (too bad that we didn't
1077 prototype signal handlers as __stdcall), calls _set_process_mask
1078 to restore any mask, restores any potentially clobbered registered
1079 and returns to orignal caller. */
1097 call _set_process_mask@4
1098 popl %%eax # saved errno
1099 testl %%eax,%%eax # Is it < 0
1100 jl 1f # yup. ignore it
1113 pushl %2 # original return address
1121 pushl %7 # saved errno
1123 pushl %4 # signal argument
1126 call _reset_signal_arrived@0
1127 # pushl _signal_arrived # Everybody waiting for this should
1128 # call _ResetEvent@4 # have woken up by now.
1131 cmpl $0,_pending_signals
1135 call _sig_dispatch_pending@4
1140 " : "=m" (sigsave.sig) : "m" (&_impure_ptr->_errno),
1141 "g" (sigsave.retaddr), "g" (sigsave.oldmask), "g" (sigsave.sig),
1142 "g" (sigsave.func), "o" (pid_offset), "g" (sigsave.saved_errno)