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
22 char debugger_command[2 * MAX_PATH + 20];
25 static int handle_exceptions (EXCEPTION_RECORD *, void *, CONTEXT *, void *);
26 extern void sigreturn ();
27 extern void sigdelayed ();
28 extern void siglast ();
29 extern DWORD __sigfirst, __siglast;
32 static BOOL WINAPI ctrl_c_handler (DWORD);
33 static void really_exit (int);
34 static char windows_system_directory[1024];
35 static size_t windows_system_directory_length;
37 /* This is set to indicate that we have already exited. */
39 static NO_COPY int exit_already = 0;
40 static NO_COPY muto *mask_sync = NULL;
42 HMODULE NO_COPY cygwin_hmodule;
43 HANDLE NO_COPY console_handler_thread_waiter = NULL;
49 } status_info[] NO_COPY =
52 { X (STATUS_ABANDONED_WAIT_0) },
53 { X (STATUS_ACCESS_VIOLATION) },
54 { X (STATUS_ARRAY_BOUNDS_EXCEEDED) },
55 { X (STATUS_BREAKPOINT) },
56 { X (STATUS_CONTROL_C_EXIT) },
57 { X (STATUS_DATATYPE_MISALIGNMENT) },
58 { X (STATUS_FLOAT_DENORMAL_OPERAND) },
59 { X (STATUS_FLOAT_DIVIDE_BY_ZERO) },
60 { X (STATUS_FLOAT_INEXACT_RESULT) },
61 { X (STATUS_FLOAT_INVALID_OPERATION) },
62 { X (STATUS_FLOAT_OVERFLOW) },
63 { X (STATUS_FLOAT_STACK_CHECK) },
64 { X (STATUS_FLOAT_UNDERFLOW) },
65 { X (STATUS_GUARD_PAGE_VIOLATION) },
66 { X (STATUS_ILLEGAL_INSTRUCTION) },
67 { X (STATUS_INTEGER_DIVIDE_BY_ZERO) },
68 { X (STATUS_INTEGER_OVERFLOW) },
69 { X (STATUS_INVALID_DISPOSITION) },
70 { X (STATUS_IN_PAGE_ERROR) },
71 { X (STATUS_NONCONTINUABLE_EXCEPTION) },
72 { X (STATUS_NO_MEMORY) },
73 { X (STATUS_PENDING) },
74 { X (STATUS_PRIVILEGED_INSTRUCTION) },
75 { X (STATUS_SINGLE_STEP) },
76 { X (STATUS_STACK_OVERFLOW) },
77 { X (STATUS_TIMEOUT) },
78 { X (STATUS_USER_APC) },
79 { X (STATUS_WAIT_0) },
84 /* Initialization code. */
88 // Set up the exception handler for the current thread. The PowerPC & Mips
89 // use compiler generated tables to set up the exception handlers for each
90 // region of code, and the kernel walks the call list until it finds a region
91 // of code that handles exceptions. The x86 on the other hand uses segment
92 // register fs, offset 0 to point to the current exception handler.
94 asm (".equ __except_list,0");
96 extern exception_list *_except_list asm ("%fs:__except_list");
99 init_exception_handler (exception_list *el)
101 el->handler = handle_exceptions;
102 el->prev = _except_list;
106 #define INIT_EXCEPTION_HANDLER(el) init_exception_handler (el)
110 set_console_handler ()
112 /* Initialize global security attribute stuff */
114 sec_none.nLength = sec_none_nih.nLength =
115 sec_all.nLength = sec_all_nih.nLength = sizeof (SECURITY_ATTRIBUTES);
116 sec_none.bInheritHandle = sec_all.bInheritHandle = TRUE;
117 sec_none_nih.bInheritHandle = sec_all_nih.bInheritHandle = FALSE;
118 sec_none.lpSecurityDescriptor = sec_none_nih.lpSecurityDescriptor = NULL;
119 sec_all.lpSecurityDescriptor = sec_all_nih.lpSecurityDescriptor =
122 /* Allocate the event needed for ctrl_c_handler synchronization with
124 if (!console_handler_thread_waiter)
125 CreateEvent (&sec_none_nih, TRUE, TRUE, NULL);
126 (void) SetConsoleCtrlHandler (ctrl_c_handler, FALSE);
127 if (!SetConsoleCtrlHandler (ctrl_c_handler, TRUE))
128 system_printf ("SetConsoleCtrlHandler failed, %E");
132 init_exceptions (exception_list *el)
134 #ifdef INIT_EXCEPTION_HANDLER
135 INIT_EXCEPTION_HANDLER (el);
140 error_start_init (const char *buf)
144 debugger_command[0] = '\0';
148 char myself_posix_name[MAX_PATH];
150 /* FIXME: gdb cannot use win32 paths, but what if debugger isn't gdb? */
151 cygwin_conv_to_posix_path (myself->progname, myself_posix_name);
152 __small_sprintf (debugger_command, "%s %s", buf, myself_posix_name);
155 /* Utilities for dumping the stack, etc. */
158 exception (EXCEPTION_RECORD *e, CONTEXT *in)
160 const char *exception_name = 0;
164 for (int i = 0; status_info[i].name; i++)
166 if (status_info[i].code == e->ExceptionCode)
168 exception_name = status_info[i].name;
177 small_printf ("Exception: %s at eip=%08x\r\n", exception_name, in->Eip);
179 small_printf ("Exception %d at eip=%08x\r\n", e->ExceptionCode, in->Eip);
180 small_printf ("eax=%08x ebx=%08x ecx=%08x edx=%08x esi=%08x edi=%08x\r\n",
181 in->Eax, in->Ebx, in->Ecx, in->Edx, in->Esi, in->Edi);
182 small_printf ("ebp=%08x esp=%08x program=%s\r\n",
183 in->Ebp, in->Esp, myself->progname);
184 small_printf ("cs=%04x ds=%04x es=%04x fs=%04x gs=%04x ss=%04x\r\n",
185 in->SegCs, in->SegDs, in->SegEs, in->SegFs, in->SegGs, in->SegSs);
189 system_printf ("Had an exception");
194 /* Print a stack backtrace. */
196 #define HAVE_STACK_TRACE
198 /* A class for manipulating the stack. */
201 int first_time; /* True if just starting to iterate. */
202 int walk (); /* Uses the "old" method */
204 STACKFRAME sf; /* For storing the stack information */
205 void init (DWORD); /* Called the first time that stack info is needed */
206 stack_info (): first_time(1) {}
208 /* Postfix ++ iterates over the stack, returning zero when nothing is left. */
209 int operator ++(int) { return this->walk (); }
212 /* The number of parameters used in STACKFRAME */
213 #define NPARAMS (sizeof(thestack.sf.Params) / sizeof(thestack.sf.Params[0]))
215 /* This is the main stack frame info for this process. */
216 static NO_COPY stack_info thestack;
217 signal_dispatch sigsave;
219 /* Initialize everything needed to start iterating. */
221 stack_info::init (DWORD ebp)
224 memset (&sf, 0, sizeof(sf));
225 sf.AddrFrame.Offset = ebp;
226 sf.AddrPC.Offset = ((DWORD *) ebp)[1];
227 sf.AddrFrame.Mode = AddrModeFlat;
230 /* Walk the stack by looking at successive stored 'bp' frames.
231 This is not foolproof. */
237 /* Everything is filled out already */
238 ebp = (char **) sf.AddrFrame.Offset;
239 else if ((ebp = (char **) *(char **) sf.AddrFrame.Offset) != NULL)
241 sf.AddrFrame.Offset = (DWORD) ebp;
242 sf.AddrPC.Offset = sf.AddrReturn.Offset;
248 if (!sf.AddrPC.Offset)
249 return 0; /* stack frames are exhausted */
251 /* The return address always follows the stack pointer */
252 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;
266 thestack.init (cx->Ebp); /* Initialize from the input CONTEXT */
267 small_printf ("Stack trace:\r\nFrame Function Args\r\n");
268 for (i = 0; i < 16 && thestack++ ; i++)
270 small_printf ("%08x %08x ", thestack.sf.AddrFrame.Offset,
271 thestack.sf.AddrPC.Offset);
272 for (unsigned j = 0; j < NPARAMS; j++)
273 small_printf ("%s%08x", j == 0 ? " (" : ", ", thestack.sf.Params[j]);
274 small_printf (")\r\n");
276 small_printf ("End of stack trace%s",
277 i == 16 ? " (more stack frames may be present)" : "");
280 /* Temporary (?) function for external callers to get a stack dump */
285 c.ContextFlags = CONTEXT_FULL;
286 GetThreadContext (GetCurrentThread (), &c);
290 static int NO_COPY keep_looping = 0;
295 debug_printf ("debugger_command %s", debugger_command);
296 if (*debugger_command == '\0')
299 __small_sprintf (strchr (debugger_command, '\0'), " %u", GetCurrentProcessId ());
303 PROCESS_INFORMATION pi = {NULL, 0, 0, 0};
305 STARTUPINFO si = {0, NULL, NULL, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL};
306 si.lpReserved = NULL;
311 /* FIXME: need to know handles of all running threads to
312 suspend_all_threads_except (current_thread_id);
315 /* if any of these mutexes is owned, we will fail to start any cygwin app
316 until trapped app exits */
318 ReleaseMutex (pinfo_mutex);
319 ReleaseMutex (title_mutex);
321 dbg = CreateProcess (NULL,
326 CREATE_NEW_CONSOLE | CREATE_NEW_PROCESS_GROUP,
333 system_printf ("Failed to start debugger: %E");
334 /* FIXME: need to know handles of all running threads to
335 resume_all_threads_except (current_thread_id);
349 stackdump (EXCEPTION_RECORD *e, CONTEXT *in)
352 if (myself->progname[0])
354 /* write to progname.stackdump if possible */
355 if ((p = strrchr (myself->progname, '\\')))
358 p = myself->progname;
359 char corefile[strlen(p) + sizeof(".stackdump")];
360 __small_sprintf (corefile, "%s.stackdump", p);
361 HANDLE h = CreateFile (corefile, GENERIC_WRITE, 0, &sec_none_nih,
362 CREATE_ALWAYS, 0, 0);
363 if (h != INVALID_HANDLE_VALUE)
365 system_printf ("Dumping stack trace to %s", corefile);
366 SetStdHandle (STD_ERROR_HANDLE, h);
374 /* Main exception handler. */
377 handle_exceptions (EXCEPTION_RECORD *e, void *, CONTEXT *in, void *)
381 /* If we've already exited, don't do anything here. Returning 1
382 tells Windows to keep looking for an exception handler. */
386 /* Coerce win32 value to posix value. */
387 switch (e->ExceptionCode)
389 case STATUS_FLOAT_DENORMAL_OPERAND:
390 case STATUS_FLOAT_DIVIDE_BY_ZERO:
391 case STATUS_FLOAT_INEXACT_RESULT:
392 case STATUS_FLOAT_INVALID_OPERATION:
393 case STATUS_FLOAT_OVERFLOW:
394 case STATUS_FLOAT_STACK_CHECK:
395 case STATUS_FLOAT_UNDERFLOW:
396 case STATUS_INTEGER_DIVIDE_BY_ZERO:
397 case STATUS_INTEGER_OVERFLOW:
401 case STATUS_ILLEGAL_INSTRUCTION:
402 case STATUS_PRIVILEGED_INSTRUCTION:
403 case STATUS_NONCONTINUABLE_EXCEPTION:
411 case STATUS_ACCESS_VIOLATION:
412 case STATUS_DATATYPE_MISALIGNMENT:
413 case STATUS_ARRAY_BOUNDS_EXCEEDED:
414 case STATUS_GUARD_PAGE_VIOLATION:
415 case STATUS_IN_PAGE_ERROR:
416 case STATUS_NO_MEMORY:
417 case STATUS_INVALID_DISPOSITION:
418 case STATUS_STACK_OVERFLOW:
422 case STATUS_CONTROL_C_EXIT:
426 case STATUS_INVALID_HANDLE:
427 /* CloseHandle will throw this exception if it is given an
428 invalid handle. We don't care about the exception; we just
429 want CloseHandle to return an error. This can be revisited
430 if gcc ever supports Windows style structured exception
435 /* If we don't recognize the exception, we have to assume that
436 we are doing structured exception handling, and we let
437 something else handle it. */
441 debug_printf ("In cygwin_except_handler exc %p at %p sp %p", e->ExceptionCode, in->Eip, in->Esp);
442 debug_printf ("In cygwin_except_handler sig = %d at %p", sig, in->Eip);
444 if (myself->getsig(sig).sa_mask & SIGTOMASK (sig))
445 syscall_printf ("signal %d, masked %p", sig, myself->getsig(sig).sa_mask);
447 if (!myself->progname[0]
448 || (void *) myself->getsig(sig).sa_handler == (void *) SIG_DFL
449 || (void *) myself->getsig(sig).sa_handler == (void *) SIG_IGN
450 || (void *) myself->getsig(sig).sa_handler == (void *) SIG_ERR)
452 static NO_COPY int traced = 0;
454 /* Print the exception to the console */
457 for (int i = 0; status_info[i].name; i++)
459 if (status_info[i].code == e->ExceptionCode)
461 system_printf ("Exception: %s", status_info[i].name);
467 /* Another exception could happen while tracing or while exiting.
468 Only do this once. */
470 system_printf ("Error while dumping state (probably corrupted stack)");
474 DuplicateHandle (hMainProc, GetCurrentThread (),
475 hMainProc, &hthread, 0, FALSE, DUPLICATE_SAME_ACCESS);
479 really_exit (EXIT_SIGNAL | sig);
482 debug_printf ("In cygwin_except_handler calling %p",
483 myself->getsig(sig).sa_handler);
485 DWORD *ebp = (DWORD *)in->Esp;
486 for (DWORD *bpend = ebp - 16; ebp > bpend; ebp--)
487 if (*ebp == in->SegCs && ebp[-1] == in->Eip)
493 sig_send (NULL, sig, (DWORD) ebp); // Signal myself
496 #endif /* __i386__ */
498 #ifndef HAVE_STACK_TRACE
502 system_printf ("Stack trace not yet supported on this machine.");
506 /* Utilities to call a user supplied exception handler. */
508 #define SIG_NONMASKABLE (SIGTOMASK (SIGCONT) | SIGTOMASK (SIGKILL) | SIGTOMASK (SIGSTOP))
511 #define HAVE_CALL_HANDLER
513 /* Non-raceable sigsuspend
514 * Note: This implementation is based on the Single UNIX Specification
515 * man page. This indicates that sigsuspend always returns -1 and that
516 * attempts to block unblockable signals will be silently ignored.
517 * This is counter to what appears to be documented in some UNIX
518 * man pages, e.g. Linux.
521 handle_sigsuspend (sigset_t tempmask)
523 sigset_t oldmask = myself->getsigmask (); // Remember for restoration
525 set_process_mask (tempmask & ~SIG_NONMASKABLE);// Let signals we're
526 // interested in through.
527 sigproc_printf ("old mask %x, new mask %x", oldmask, tempmask);
529 WaitForSingleObject (signal_arrived, INFINITE);
531 set_sig_errno (EINTR); // Per POSIX
533 /* A signal dispatch function will have been added to our stack and will
534 be hit eventually. Set the old mask to be restored when the signal
537 sigsave.oldmask = oldmask; // Will be restored by signal handler
541 extern DWORD exec_exit; // Possible exit value for exec
542 extern int pending_signals;
545 interruptible (DWORD pc, int testvalid = 0)
548 if ((pc >= (DWORD) &__sigfirst) && (pc <= (DWORD) &__siglast))
552 MEMORY_BASIC_INFORMATION m;
553 memset (&m, 0, sizeof m);
554 if (!VirtualQuery ((LPCVOID) pc, &m, sizeof m))
555 sigproc_printf ("couldn't get memory info, %E");
557 char *checkdir = (char *) alloca (windows_system_directory_length + 4);
558 memset (checkdir, 0, sizeof (checkdir));
559 # define h ((HMODULE) m.AllocationBase)
560 /* Apparently Windows 95 can sometimes return bogus addresses from
561 GetThreadContext. These resolve to an allocation base == 0.
562 These should *never* be treated as interruptible. */
566 res = 1; /* All we wanted to know was if this was a valid module. */
567 else if (h == user_data->hmodule)
569 else if (h == cygwin_hmodule)
571 else if (!GetModuleFileName (h, checkdir, windows_system_directory_length + 2))
574 res = !strncasematch (windows_system_directory, checkdir,
575 windows_system_directory_length);
576 minimal_printf ("h %p", h);
580 minimal_printf ("interruptible %d", res);
584 static void __stdcall
585 interrupt_setup (int sig, struct sigaction& siga, void *handler,
586 DWORD retaddr, DWORD *retaddr_on_stack)
588 sigsave.retaddr = retaddr;
589 sigsave.retaddr_on_stack = retaddr_on_stack;
590 sigsave.oldmask = myself->getsigmask (); // Remember for restoration
591 /* FIXME: Not multi-thread aware */
592 set_process_mask (myself->getsigmask () | siga.sa_mask | SIGTOMASK (sig));
593 sigsave.func = (void (*)(int)) handler;
595 sigsave.saved_errno = -1; // Flag: no errno to save
599 interrupt_now (CONTEXT *ctx, int sig, struct sigaction& siga, void *handler)
601 interrupt_setup (sig, siga, handler, ctx->Eip, 0);
602 ctx->Eip = (DWORD) sigdelayed;
603 SetThreadContext (myself->getthread2signal(), ctx); /* Restart the thread */
607 signal_fixup_after_fork ()
613 if (sigsave.retaddr_on_stack)
615 *sigsave.retaddr_on_stack = sigsave.retaddr;
616 set_process_mask (sigsave.oldmask);
621 interrupt_on_return (DWORD ebp, int sig, struct sigaction& siga, void *handler)
626 return 0; /* Already have a signal stacked up */
628 thestack.init (ebp); /* Initialize from the input CONTEXT */
629 for (i = 0; i < 32 && thestack++ ; i++)
630 if (interruptible (thestack.sf.AddrReturn.Offset))
632 DWORD *addr_retaddr = ((DWORD *)thestack.sf.AddrFrame.Offset) + 1;
633 if (*addr_retaddr == thestack.sf.AddrReturn.Offset)
635 interrupt_setup (sig, siga, handler, *addr_retaddr, addr_retaddr);
636 *addr_retaddr = (DWORD) sigdelayed;
641 api_fatal ("couldn't send signal %d", sig);
645 extern "C" void __stdcall
646 set_sig_errno (int e)
649 sigsave.saved_errno = e;
650 debug_printf ("errno %d", e);
653 #define SUSPEND_TRIES 10000
656 call_handler (int sig, struct sigaction& siga, void *handler)
663 int using_mainthread_frame;
665 mainthread.lock->acquire ();
667 if (mainthread.frame)
669 ebp = mainthread.frame;
670 using_mainthread_frame = 1;
675 using_mainthread_frame = 0;
676 mainthread.lock->release ();
678 hth = myself->getthread2signal ();
679 /* Suspend the thread which will receive the signal. But first ensure that
680 this thread doesn't have any mutos. (FIXME: Someday we should just grab
681 all of the mutos rather than checking for them)
682 For Windows 95, we also have to ensure that the addresses returned by GetThreadContext
684 If one of these conditions is not true we loop for a fixed number of times
685 since we don't want to stall the signal handler. FIXME: Will this result in
687 If the thread is already suspended (which can occur when a program is stopped) then
688 just queue the signal. */
689 for (i = 0; i < SUSPEND_TRIES; i++)
691 sigproc_printf ("suspending mainthread");
692 res = SuspendThread (hth);
695 /* FIXME: Make multi-thread aware */
696 for (m = muto_start.next; m != NULL; m = m->next)
697 if (m->unstable () || m->owner () == mainthread.id)
700 mainthread.lock->acquire ();
701 if (mainthread.frame)
703 ebp = mainthread.frame; /* try to avoid a race */
704 using_mainthread_frame = 1;
707 mainthread.lock->release ();
709 cx.ContextFlags = CONTEXT_CONTROL | CONTEXT_INTEGER;
710 if (!GetThreadContext (hth, &cx))
712 system_printf ("couldn't get context of main thread, %E");
716 if (interruptible (cx.Eip, 1))
719 sigproc_printf ("suspended thread in a strange state pc %p, sp %p",
724 sigproc_printf ("suspended thread owns a muto (%s)", m->name);
734 if (i >= SUSPEND_TRIES)
737 sigproc_printf ("SuspendThread returned %d", res);
742 if (hExeced != NULL || (!using_mainthread_frame && interruptible (cx.Eip)))
743 interrupt_now (&cx, sig, siga, handler);
744 else if (!interrupt_on_return (ebp, sig, siga, handler))
747 pending_signals = 1; /* FIXME: Probably need to be more tricky here */
748 sig_set_pending (sig);
754 res = SetEvent (signal_arrived); // For an EINTR case
755 sigproc_printf ("armed signal_arrived %p, res %d", signal_arrived, res);
756 /* Clear any waiting threads prior to dispatching to handler function */
757 proc_subproc(PROC_CLEARWAIT, 1);
762 sigproc_printf ("modified main-thread stack");
765 res = ResumeThread (hth);
766 sigproc_printf ("ResumeThread returned %d", res);
769 mainthread.lock->release ();
771 sigproc_printf ("returning %d", interrupted);
776 #ifndef HAVE_CALL_HANDLER
777 #error "Need to supply machine dependent call_handler"
780 /* Keyboard interrupt handler. */
782 ctrl_c_handler (DWORD type)
784 if (type == CTRL_LOGOFF_EVENT)
787 /* Wait for sigproc_init to tell us that it's safe to send something.
788 This event will always be in a signalled state when wait_sig is
789 ready to process signals. */
790 (void) WaitForSingleObject (console_handler_thread_waiter, 5000);
792 if ((type == CTRL_CLOSE_EVENT) || (type == CTRL_SHUTDOWN_EVENT))
793 /* Return FALSE to prevent an "End task" dialog box from appearing
794 for each Cygwin process window that's open when the computer
795 is shut down or console window is closed. */
797 sig_send (NULL, SIGHUP);
800 tty_min *t = cygwin_shared->tty.get_tty(myself->ctty);
801 /* Ignore this if we're not the process group lead since it should be handled
802 *by* the process group leader. */
803 if (t->getpgid () != myself->pid ||
804 (GetTickCount () - t->last_ctrl_c) < MIN_CTRL_C_SLOP)
807 /* Otherwise we just send a SIGINT to the process group and return TRUE (to indicate
808 that we have handled the signal). At this point, type should be
809 a CTRL_C_EVENT or CTRL_BREAK_EVENT. */
811 t->last_ctrl_c = GetTickCount ();
812 kill (-myself->pid, SIGINT);
813 t->last_ctrl_c = GetTickCount ();
818 /* Set the signal mask for this process.
819 * Note that some signals are unmaskable, as in UNIX.
821 extern "C" void __stdcall
822 set_process_mask (sigset_t newmask)
826 mask_sync->acquire (INFINITE);
827 sigset_t oldmask = myself->getsigmask ();
828 newmask &= ~SIG_NONMASKABLE;
829 sigproc_printf ("old mask = %x, new mask = %x", myself->getsigmask (), newmask);
830 myself->setsigmask (newmask); // Set a new mask
831 mask_sync->release ();
832 if (oldmask != newmask && GetCurrentThreadId () != sigtid)
833 sig_dispatch_pending ();
839 sig_handle_tty_stop (int sig)
844 /* Be sure that process's main thread isn't an owner of vital
845 mutex to prevent cygwin subsystem lockups */
846 waitbuf[0] = pinfo_mutex;
847 waitbuf[1] = title_mutex;
848 WaitForMultipleObjects (2, waitbuf, TRUE, INFINITE);
849 ReleaseMutex (pinfo_mutex);
850 ReleaseMutex (title_mutex);
852 myself->stopsig = sig;
853 myself->process_state |= PID_STOPPED;
854 /* See if we have a living parent. If so, send it a special signal.
855 * It will figure out exactly which pid has stopped by scanning
856 * its list of subprocesses.
858 if (my_parent_is_alive ())
860 pinfo *parent = procinfo(myself->ppid);
861 sig_send (parent, __SIGCHILDSTOPPED);
863 sigproc_printf ("process %d stopped by signal %d, parent_alive %p",
864 myself->pid, sig, parent_alive);
865 /* There is a small race here with the above two mutexes */
866 SuspendThread (hMainThread);
876 sigproc_printf ("signal %d", sig);
878 struct sigaction thissig = myself->getsig(sig);
879 void *handler = (void *) thissig.sa_handler;
881 myself->rusage_self.ru_nsignals++;
883 /* Clear pending SIGCONT on stop signals */
884 if (sig == SIGSTOP || sig == SIGTSTP || sig == SIGTTIN || sig == SIGTTOU)
893 /* FIXME: Should we still do this if SIGCONT has a handler? */
897 myself->process_state &= ~PID_STOPPED;
898 /* Clear pending stop signals */
903 /* Windows 95 hangs on resuming non-suspended thread */
904 SuspendThread (hMainThread);
905 while (ResumeThread (hMainThread) > 1)
907 /* process pending signals */
908 sig_dispatch_pending ();
913 __small_sprintf (sigmsg, "cygwin: signal %d\n", sig);
914 OutputDebugString (sigmsg);
917 if (handler == (void *) SIG_DFL)
919 if (sig == SIGCHLD || sig == SIGIO || sig == SIGCONT || sig == SIGWINCH)
921 sigproc_printf ("default signal %d ignored", sig);
925 if (sig == SIGTSTP || sig == SIGTTIN || sig == SIGTTOU)
931 if (handler == (void *) SIG_IGN)
933 sigproc_printf ("signal %d ignored", sig);
937 if (handler == (void *) SIG_ERR)
940 if ((sig == SIGCHLD) && (thissig.sa_flags & SA_NOCLDSTOP))
946 handler = (void *) sig_handle_tty_stop;
949 /* Dispatch to the appropriate function. */
950 sigproc_printf ("signal %d, about to call %p", sig, thissig.sa_handler);
951 rc = call_handler (sig, thissig, handler);
954 sigproc_printf ("returning %d", rc);
958 if (sig == SIGQUIT || sig == SIGABRT)
960 stackdump (NULL, NULL);
963 sigproc_printf ("signal %d, about to call do_exit", sig);
964 TerminateThread (hMainThread, 0);
965 /* FIXME: This just works around the problem so that we don't attempt to
966 use a resource lock when exiting. */
967 user_data->resourcelocks->Delete();
968 user_data->resourcelocks->Init();
969 do_exit (EXIT_SIGNAL | (sig << 8));
973 /* Cover function to `do_exit' to handle exiting even in presence of more
974 exceptions. We use to call exit, but a SIGSEGV shouldn't cause atexit
980 /* If the exception handler gets a trap, we could recurse awhile.
981 If this is non-zero, skip the cleaning up and exit NOW. */
985 /* We are going down - reset our process_state without locking. */
986 myself->record_death (FALSE);
993 HANDLE NO_COPY pinfo_mutex = NULL;
994 HANDLE NO_COPY title_mutex = NULL;
999 /* pinfo_mutex protects access to process table */
1001 if (!(pinfo_mutex = CreateMutex (&sec_all_nih, FALSE,
1002 shared_name ("pinfo_mutex", 0))))
1003 api_fatal ("catastrophic failure - unable to create pinfo_mutex, %E");
1005 ProtectHandle (pinfo_mutex);
1007 /* title_mutex protects modification of console title. It's neccessary
1008 while finding console window handle */
1010 if (!(title_mutex = CreateMutex (&sec_all_nih, FALSE,
1011 shared_name ("title_mutex", 0))))
1012 api_fatal ("can't create title mutex, %E");
1014 ProtectHandle (title_mutex);
1015 mask_sync = new_muto (FALSE, "mask_sync");
1016 windows_system_directory[0] = '\0';
1017 (void) GetSystemDirectory (windows_system_directory, sizeof (windows_system_directory) - 2);
1018 char *end = strchr (windows_system_directory, '\0');
1019 if (end == windows_system_directory)
1020 api_fatal ("can't find windows system directory");
1021 if (end[-1] != '\\')
1026 windows_system_directory_length = end - windows_system_directory;
1027 debug_printf ("windows_system_directory '%s', windows_system_directory_length %d",
1028 windows_system_directory, windows_system_directory_length);
1029 debug_printf ("cygwin_hmodule %p", cygwin_hmodule);
1033 events_terminate (void)
1035 //CloseHandle (pinfo_mutex); // Use implicit close on exit to avoid race
1036 ForceCloseHandle (title_mutex);
1040 #define pid_offset (unsigned)(((pinfo *)NULL)->pid)
1042 static void __stdcall
1043 reset_signal_arrived () __attribute__ ((unused));
1044 static void __stdcall
1045 reset_signal_arrived ()
1047 (void) ResetEvent (signal_arrived);
1048 sigproc_printf ("reset signal_arrived");
1051 void unused_sig_wrapper()
1053 /* Signal cleanup stuff. Cleans up stack (too bad that we didn't
1054 prototype signal handlers as __stdcall), calls _set_process_mask
1055 to restore any mask, restores any potentially clobbered registered
1056 and returns to orignal caller. */
1074 call _set_process_mask@4
1075 popl %%eax # saved errno
1076 testl %%eax,%%eax # Is it < 0
1077 jl 1f # yup. ignore it
1090 pushl %2 # original return address
1098 pushl %7 # saved errno
1100 pushl %4 # signal argument
1103 call _reset_signal_arrived@0
1106 cmpl $0,_pending_signals
1110 call _sig_dispatch_pending@4
1115 " : "=m" (sigsave.sig) : "m" (&_impure_ptr->_errno),
1116 "g" (sigsave.retaddr), "g" (sigsave.oldmask), "g" (sigsave.sig),
1117 "g" (sigsave.func), "o" (pid_offset), "g" (sigsave.saved_errno)