OSDN Git Service

* Makefile.in: Remove libadvapi32.a.
[pf3gnuchains/pf3gnuchains3x.git] / winsup / cygwin / exceptions.cc
1 /* exceptions.cc
2
3    Copyright 1996, 1997, 1998, 1999, 2000 Cygnus Solutions.
4
5 This file is part of Cygwin.
6
7 This software is a copyrighted work licensed under the terms of the
8 Cygwin license.  Please consult the file "CYGWIN_LICENSE" for
9 details. */
10
11 #include <stdio.h>
12 #include <errno.h>
13
14 #define Win32_Winsock
15 #include "winsup.h"
16 #include "exceptions.h"
17 #undef DECLSPEC_IMPORT
18 #define DECLSPEC_IMPORT
19 #include <imagehlp.h>
20 #include "autoload.h"
21
22 char debugger_command[2 * MAX_PATH + 20];
23
24 extern "C" {
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;
30 };
31
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;
36
37 /* This is set to indicate that we have already exited.  */
38
39 static NO_COPY int exit_already = 0;
40 static NO_COPY muto *mask_sync = NULL;
41
42 HMODULE NO_COPY cygwin_hmodule;
43 HANDLE NO_COPY console_handler_thread_waiter = NULL;
44
45 static const struct
46 {
47   unsigned int code;
48   const char *name;
49 } status_info[] NO_COPY =
50 {
51 #define X(s) s, #s
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) },
80   { 0, 0 }
81 #undef X
82 };
83
84 /* Initialization code.  */
85
86 #ifdef __i386__
87
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.
93
94 asm (".equ __except_list,0");
95
96 extern exception_list *_except_list asm ("%fs:__except_list");
97
98 static void
99 init_exception_handler (exception_list *el)
100 {
101   el->handler = handle_exceptions;
102   el->prev = _except_list;
103   _except_list = el;
104 }
105
106 #define INIT_EXCEPTION_HANDLER(el) init_exception_handler (el)
107 #endif
108
109 void
110 set_console_handler ()
111 {
112   /* Initialize global security attribute stuff */
113
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 =
120     get_null_sd ();
121
122   /* Allocate the event needed for ctrl_c_handler synchronization with
123      wait_sig. */
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");
129 }
130
131 extern "C" void
132 init_exceptions (exception_list *el)
133 {
134 #ifdef INIT_EXCEPTION_HANDLER
135   INIT_EXCEPTION_HANDLER (el);
136 #endif
137 }
138
139 extern "C" void
140 error_start_init (const char *buf)
141 {
142   if (!buf || !*buf)
143     {
144       debugger_command[0] = '\0';
145       return;
146     }
147
148   char myself_posix_name[MAX_PATH];
149
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);
153 }
154
155 /* Utilities for dumping the stack, etc.  */
156
157 static void
158 exception (EXCEPTION_RECORD *e,  CONTEXT *in)
159 {
160   const char *exception_name = 0;
161
162   if (e)
163     {
164       for (int i = 0; status_info[i].name; i++)
165         {
166           if (status_info[i].code == e->ExceptionCode)
167             {
168               exception_name = status_info[i].name;
169               break;
170             }
171         }
172     }
173
174 #ifdef __i386__
175 #define HAVE_STATUS
176   if (exception_name)
177     small_printf ("Exception: %s at eip=%08x\r\n", exception_name, in->Eip);
178   else
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);
186 #endif
187
188 #ifndef HAVE_STATUS
189   system_printf ("Had an exception");
190 #endif
191 }
192
193 #ifdef __i386__
194 /* Print a stack backtrace. */
195
196 #define HAVE_STACK_TRACE
197
198 /* A class for manipulating the stack. */
199 class stack_info
200 {
201   int first_time;               /* True if just starting to iterate. */
202   int walk ();                  /* Uses the "old" method */
203 public:
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) {}
207
208   /* Postfix ++ iterates over the stack, returning zero when nothing is left. */
209   int operator ++(int) { return this->walk (); }
210 };
211
212 /* The number of parameters used in STACKFRAME */
213 #define NPARAMS (sizeof(thestack.sf.Params) / sizeof(thestack.sf.Params[0]))
214
215 /* This is the main stack frame info for this process. */
216 static NO_COPY stack_info thestack;
217 signal_dispatch sigsave;
218
219 /* Initialize everything needed to start iterating. */
220 void
221 stack_info::init (DWORD ebp)
222 {
223   first_time = 1;
224   memset (&sf, 0, sizeof(sf));
225   sf.AddrFrame.Offset = ebp;
226   sf.AddrPC.Offset = ((DWORD *) ebp)[1];
227   sf.AddrFrame.Mode = AddrModeFlat;
228 }
229
230 /* Walk the stack by looking at successive stored 'bp' frames.
231    This is not foolproof. */
232 int
233 stack_info::walk ()
234 {
235   char **ebp;
236   if (first_time)
237     /* Everything is filled out already */
238     ebp = (char **) sf.AddrFrame.Offset;
239   else if ((ebp = (char **) *(char **) sf.AddrFrame.Offset) != NULL)
240     {
241       sf.AddrFrame.Offset = (DWORD) ebp;
242       sf.AddrPC.Offset = sf.AddrReturn.Offset;
243     }
244   else
245     return 0;
246
247   first_time = 0;
248   if (!sf.AddrPC.Offset)
249     return 0;           /* stack frames are exhausted */
250
251   /* The return address always follows the stack pointer */
252   sf.AddrReturn.Offset = (DWORD) *++ebp;
253
254   /* The arguments follow the return address */
255   for (unsigned i = 0; i < NPARAMS; i++)
256     sf.Params[i] = (DWORD) *++ebp;
257   return 1;
258 }
259
260 /* Dump the stack */
261 void
262 stack (CONTEXT *cx)
263 {
264   int i;
265
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++)
269     {
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");
275     }
276   small_printf ("End of stack trace%s",
277               i == 16 ? " (more stack frames may be present)" : "");
278 }
279
280 /* Temporary (?) function for external callers to get a stack dump */
281 extern "C" void
282 cygwin_stackdump()
283 {
284   CONTEXT c;
285   c.ContextFlags = CONTEXT_FULL;
286   GetThreadContext (GetCurrentThread (), &c);
287   stack(&c);
288 }
289
290 static int NO_COPY keep_looping = 0;
291
292 extern "C" int
293 try_to_debug ()
294 {
295   debug_printf ("debugger_command %s", debugger_command);
296   if (*debugger_command == '\0')
297     return 0;
298
299   __small_sprintf (strchr (debugger_command, '\0'), " %u", GetCurrentProcessId ());
300
301   BOOL dbg;
302
303   PROCESS_INFORMATION pi = {NULL, 0, 0, 0};
304
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;
307   si.lpDesktop = NULL;
308   si.dwFlags = 0;
309   si.cb = sizeof (si);
310
311   /* FIXME: need to know handles of all running threads to
312      suspend_all_threads_except (current_thread_id);
313   */
314
315   /* if any of these mutexes is owned, we will fail to start any cygwin app
316      until trapped app exits */
317
318   ReleaseMutex (pinfo_mutex);
319   ReleaseMutex (title_mutex);
320
321   dbg = CreateProcess (NULL,
322                        debugger_command,
323                        NULL,
324                        NULL,
325                        FALSE,
326                        CREATE_NEW_CONSOLE | CREATE_NEW_PROCESS_GROUP,
327                        NULL,
328                        NULL,
329                        &si,
330                        &pi);
331   if (!dbg)
332     {
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);
336       */
337     }
338   else
339     {
340       keep_looping = 1;
341       while (keep_looping)
342         Sleep (10000);
343     }
344
345   return 0;
346 }
347
348 void
349 stackdump (EXCEPTION_RECORD *e, CONTEXT *in)
350 {
351   char *p;
352   if (myself->progname[0])
353     {
354       /* write to progname.stackdump if possible */
355       if ((p = strrchr (myself->progname, '\\')))
356         p++;
357       else
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)
364         {
365           system_printf ("Dumping stack trace to %s", corefile);
366           SetStdHandle (STD_ERROR_HANDLE, h);
367         }
368     }
369   if (e)
370     exception (e, in);
371   stack (in);
372 }
373
374 /* Main exception handler. */
375
376 static int
377 handle_exceptions (EXCEPTION_RECORD *e, void *, CONTEXT *in, void *)
378 {
379   int sig;
380
381   /* If we've already exited, don't do anything here.  Returning 1
382      tells Windows to keep looking for an exception handler.  */
383   if (exit_already)
384     return 1;
385
386   /* Coerce win32 value to posix value.  */
387   switch (e->ExceptionCode)
388     {
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:
398       sig = SIGFPE;
399       break;
400
401     case STATUS_ILLEGAL_INSTRUCTION:
402     case STATUS_PRIVILEGED_INSTRUCTION:
403     case STATUS_NONCONTINUABLE_EXCEPTION:
404       sig = SIGILL;
405       break;
406
407     case STATUS_TIMEOUT:
408       sig = SIGALRM;
409       break;
410
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:
419       sig = SIGSEGV;
420       break;
421
422     case STATUS_CONTROL_C_EXIT:
423       sig = SIGINT;
424       break;
425
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
431          handling.  */
432       return 0;
433
434     default:
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.  */
438       return 1;
439     }
440
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);
443
444   if (myself->getsig(sig).sa_mask & SIGTOMASK (sig))
445     syscall_printf ("signal %d, masked %p", sig, myself->getsig(sig).sa_mask);
446
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)
451     {
452       static NO_COPY int traced = 0;
453
454       /* Print the exception to the console */
455       if (e)
456         {
457           for (int i = 0; status_info[i].name; i++)
458             {
459               if (status_info[i].code == e->ExceptionCode)
460                 {
461                   system_printf ("Exception: %s", status_info[i].name);
462                   break;
463                 }
464             }
465         }
466
467       /* Another exception could happen while tracing or while exiting.
468          Only do this once.  */
469       if (traced++)
470         system_printf ("Error while dumping state (probably corrupted stack)");
471       else
472         {
473           HANDLE hthread;
474           DuplicateHandle (hMainProc, GetCurrentThread (),
475                            hMainProc, &hthread, 0, FALSE, DUPLICATE_SAME_ACCESS);
476           stackdump (e, in);
477         }
478       try_to_debug ();
479       really_exit (EXIT_SIGNAL | sig);
480     }
481
482   debug_printf ("In cygwin_except_handler calling %p",
483                  myself->getsig(sig).sa_handler);
484
485   DWORD *ebp = (DWORD *)in->Esp;
486   for (DWORD *bpend = ebp - 16; ebp > bpend; ebp--)
487     if (*ebp == in->SegCs && ebp[-1] == in->Eip)
488       {
489         ebp -= 2;
490         break;
491       }
492
493   sig_send (NULL, sig, (DWORD) ebp);            // Signal myself
494   return 0;
495 }
496 #endif /* __i386__ */
497
498 #ifndef HAVE_STACK_TRACE
499 void
500 stack (void)
501 {
502   system_printf ("Stack trace not yet supported on this machine.");
503 }
504 #endif
505
506 /* Utilities to call a user supplied exception handler.  */
507
508 #define SIG_NONMASKABLE (SIGTOMASK (SIGCONT) | SIGTOMASK (SIGKILL) | SIGTOMASK (SIGSTOP))
509
510 #ifdef __i386__
511 #define HAVE_CALL_HANDLER
512
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.
519  */
520 int __stdcall
521 handle_sigsuspend (sigset_t tempmask)
522 {
523   sigset_t oldmask = myself->getsigmask ();     // Remember for restoration
524
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);
528
529   WaitForSingleObject (signal_arrived, INFINITE);
530
531   set_sig_errno (EINTR);        // Per POSIX
532
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
535      handler returns. */
536
537   sigsave.oldmask = oldmask;    // Will be restored by signal handler
538   return -1;
539 }
540
541 extern DWORD exec_exit;         // Possible exit value for exec
542 extern int pending_signals;
543
544 int
545 interruptible (DWORD pc, int testvalid = 0)
546 {
547   int res;
548   if ((pc >= (DWORD) &__sigfirst) && (pc <= (DWORD) &__siglast))
549     res = 0;
550   else
551     {
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");
556
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. */
563       if (!h)
564         res = 0;
565       else if (testvalid)
566         res = 1;        /* All we wanted to know was if this was a valid module. */
567       else if (h == user_data->hmodule)
568         res = 1;
569       else if (h == cygwin_hmodule)
570         res = 0;
571       else if (!GetModuleFileName (h, checkdir, windows_system_directory_length + 2))
572         res = 0;
573       else
574         res = !strncasematch (windows_system_directory, checkdir,
575                               windows_system_directory_length);
576       minimal_printf ("h %p", h);
577 #     undef h
578     }
579
580   minimal_printf ("interruptible %d", res);
581   return res;
582 }
583
584 static void __stdcall
585 interrupt_setup (int sig, struct sigaction& siga, void *handler,
586                  DWORD retaddr, DWORD *retaddr_on_stack)
587 {
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;
594   sigsave.sig = sig;
595   sigsave.saved_errno = -1;             // Flag: no errno to save
596 }
597
598 static void
599 interrupt_now (CONTEXT *ctx, int sig, struct sigaction& siga, void *handler)
600 {
601   interrupt_setup (sig, siga, handler, ctx->Eip, 0);
602   ctx->Eip = (DWORD) sigdelayed;
603   SetThreadContext (myself->getthread2signal(), ctx); /* Restart the thread */
604 }
605
606 void __cdecl
607 signal_fixup_after_fork ()
608 {
609   if (!sigsave.sig)
610     return;
611
612   sigsave.sig = 0;
613   if (sigsave.retaddr_on_stack)
614     {
615       *sigsave.retaddr_on_stack = sigsave.retaddr;
616       set_process_mask (sigsave.oldmask);
617     }
618 }
619   
620 static int
621 interrupt_on_return (DWORD ebp, int sig, struct sigaction& siga, void *handler)
622 {
623   int i;
624
625   if (sigsave.sig)
626     return 0;   /* Already have a signal stacked up */
627
628   thestack.init (ebp);  /* Initialize from the input CONTEXT */
629   for (i = 0; i < 32 && thestack++ ; i++)
630     if (interruptible (thestack.sf.AddrReturn.Offset))
631       {
632         DWORD *addr_retaddr = ((DWORD *)thestack.sf.AddrFrame.Offset) + 1;
633         if (*addr_retaddr  == thestack.sf.AddrReturn.Offset)
634           {
635             interrupt_setup (sig, siga, handler, *addr_retaddr, addr_retaddr);
636             *addr_retaddr = (DWORD) sigdelayed;
637           }
638         return 1;
639       }
640
641   api_fatal ("couldn't send signal %d", sig);
642   return 0;
643 }
644
645 extern "C" void __stdcall
646 set_sig_errno (int e)
647 {
648   set_errno (e);
649   sigsave.saved_errno = e;
650   debug_printf ("errno %d", e);
651 }
652
653 #define SUSPEND_TRIES 10000
654
655 static int
656 call_handler (int sig, struct sigaction& siga, void *handler)
657 {
658   CONTEXT cx;
659   int interrupted = 1;
660   HANDLE hth = NULL;
661   DWORD ebp;
662   int res;
663   int using_mainthread_frame;
664
665   mainthread.lock->acquire ();
666
667   if (mainthread.frame)
668     {
669       ebp = mainthread.frame;
670       using_mainthread_frame = 1;
671     }
672   else
673     {
674       int i;
675       using_mainthread_frame = 0;
676       mainthread.lock->release ();
677
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
683          are valid.
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
686          noticeable delays?
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++)
690         {
691           sigproc_printf ("suspending mainthread");
692           res = SuspendThread (hth);
693
694           muto *m;
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)
698               goto owns_muto;
699
700           mainthread.lock->acquire ();
701           if (mainthread.frame)
702             {
703               ebp = mainthread.frame;   /* try to avoid a race */
704               using_mainthread_frame = 1;
705               goto next;
706             }
707           mainthread.lock->release ();
708
709           cx.ContextFlags = CONTEXT_CONTROL | CONTEXT_INTEGER;
710           if (!GetThreadContext (hth, &cx))
711             {
712               system_printf ("couldn't get context of main thread, %E");
713               goto out;
714             }
715
716           if (interruptible (cx.Eip, 1))
717             break;
718
719           sigproc_printf ("suspended thread in a strange state pc %p, sp %p",
720                           cx.Eip, cx.Esp);
721           goto resume_thread;
722
723         owns_muto:
724           sigproc_printf ("suspended thread owns a muto (%s)", m->name);
725           
726           if (res)
727             goto set_pending;
728
729         resume_thread:
730           ResumeThread (hth);
731           Sleep (0);
732         }
733
734       if (i >= SUSPEND_TRIES)
735         goto set_pending;
736
737       sigproc_printf ("SuspendThread returned %d", res);
738       ebp = cx.Ebp;
739     }
740
741 next:
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))
745     {
746     set_pending:
747       pending_signals = 1;      /* FIXME: Probably need to be more tricky here */
748       sig_set_pending (sig);
749       interrupted = 0;
750     }
751
752   if (interrupted)
753     {
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);
758     }
759
760 out:
761   if (!hth)
762     sigproc_printf ("modified main-thread stack");
763   else
764     {
765       res = ResumeThread (hth);
766       sigproc_printf ("ResumeThread returned %d", res);
767     }
768
769   mainthread.lock->release ();
770
771   sigproc_printf ("returning %d", interrupted);
772   return interrupted;
773 }
774 #endif /* i386 */
775
776 #ifndef HAVE_CALL_HANDLER
777 #error "Need to supply machine dependent call_handler"
778 #endif
779
780 /* Keyboard interrupt handler.  */
781 static BOOL WINAPI
782 ctrl_c_handler (DWORD type)
783 {
784   if (type == CTRL_LOGOFF_EVENT)
785     return TRUE;
786
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);
791
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. */
796     {
797       sig_send (NULL, SIGHUP);
798       return FALSE;
799     }
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)
805     return TRUE;
806   else
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. */
810     {
811       t->last_ctrl_c = GetTickCount ();
812       kill (-myself->pid, SIGINT);
813       t->last_ctrl_c = GetTickCount ();
814       return TRUE;
815     }
816 }
817
818 /* Set the signal mask for this process.
819  * Note that some signals are unmaskable, as in UNIX.
820  */
821 extern "C" void __stdcall
822 set_process_mask (sigset_t newmask)
823 {
824   extern DWORD sigtid;
825
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 ();
834   return;
835 }
836
837 extern "C" {
838 static void
839 sig_handle_tty_stop (int sig)
840 {
841 #if 0
842   HANDLE waitbuf[2];
843
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);
851 #endif
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.
857    */
858   if (my_parent_is_alive ())
859     {
860       pinfo *parent = procinfo(myself->ppid);
861       sig_send (parent, __SIGCHILDSTOPPED);
862     }
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);
867   return;
868 }
869 }
870
871 int __stdcall
872 sig_handle (int sig)
873 {
874   int rc = 0;
875
876   sigproc_printf ("signal %d", sig);
877
878   struct sigaction thissig = myself->getsig(sig);
879   void *handler = (void *) thissig.sa_handler;
880
881   myself->rusage_self.ru_nsignals++;
882
883   /* Clear pending SIGCONT on stop signals */
884   if (sig == SIGSTOP || sig == SIGTSTP || sig == SIGTTIN || sig == SIGTTOU)
885     sig_clear (SIGCONT);
886
887   if (sig == SIGKILL)
888     goto exit_sig;
889
890   if (sig == SIGSTOP)
891     goto stop;
892
893   /* FIXME: Should we still do this if SIGCONT has a handler? */
894   if (sig == SIGCONT)
895     {
896       myself->stopsig = 0;
897       myself->process_state &= ~PID_STOPPED;
898       /* Clear pending stop signals */
899       sig_clear (SIGSTOP);
900       sig_clear (SIGTSTP);
901       sig_clear (SIGTTIN);
902       sig_clear (SIGTTOU);
903       /* Windows 95 hangs on resuming non-suspended thread */
904       SuspendThread (hMainThread);
905       while (ResumeThread (hMainThread) > 1)
906         ;
907       /* process pending signals */
908       sig_dispatch_pending ();
909     }
910
911 #if 0
912   char sigmsg[24];
913   __small_sprintf (sigmsg, "cygwin: signal %d\n", sig);
914   OutputDebugString (sigmsg);
915 #endif
916
917   if (handler == (void *) SIG_DFL)
918     {
919       if (sig == SIGCHLD || sig == SIGIO || sig == SIGCONT || sig == SIGWINCH)
920         {
921           sigproc_printf ("default signal %d ignored", sig);
922           goto done;
923         }
924
925       if (sig == SIGTSTP || sig == SIGTTIN || sig == SIGTTOU)
926         goto stop;
927
928       goto exit_sig;
929     }
930
931   if (handler == (void *) SIG_IGN)
932     {
933       sigproc_printf ("signal %d ignored", sig);
934       goto done;
935     }
936
937   if (handler == (void *) SIG_ERR)
938     goto exit_sig;
939
940   if ((sig == SIGCHLD) && (thissig.sa_flags & SA_NOCLDSTOP))
941     goto done;
942
943   goto dosig;
944
945 stop:
946   handler = (void *) sig_handle_tty_stop;
947
948 dosig:
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);
952
953 done:
954   sigproc_printf ("returning %d", rc);
955   return rc;
956
957 exit_sig:
958   if (sig == SIGQUIT || sig == SIGABRT)
959     {
960       stackdump (NULL, NULL);
961       try_to_debug ();
962     }
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));
970   /* Never returns */
971 }
972
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
975    routines to run.  */
976
977 static void
978 really_exit (int rc)
979 {
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.  */
982
983   if (exit_already++)
984     {
985       /* We are going down - reset our process_state without locking. */
986       myself->record_death (FALSE);
987       ExitProcess (rc);
988     }
989
990   do_exit (rc);
991 }
992
993 HANDLE NO_COPY pinfo_mutex = NULL;
994 HANDLE NO_COPY title_mutex = NULL;
995
996 void
997 events_init (void)
998 {
999   /* pinfo_mutex protects access to process table */
1000
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");
1004
1005   ProtectHandle (pinfo_mutex);
1006
1007   /* title_mutex protects modification of console title. It's neccessary
1008      while finding console window handle */
1009
1010   if (!(title_mutex = CreateMutex (&sec_all_nih, FALSE,
1011                                    shared_name ("title_mutex", 0))))
1012     api_fatal ("can't create title mutex, %E");
1013
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] != '\\')
1022     {
1023       *end++ = '\\';
1024       *end = '\0';
1025     }
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);
1030 }
1031
1032 void
1033 events_terminate (void)
1034 {
1035 //CloseHandle (pinfo_mutex);    // Use implicit close on exit to avoid race
1036   ForceCloseHandle (title_mutex);
1037   exit_already = 1;
1038 }
1039
1040 #define pid_offset (unsigned)(((pinfo *)NULL)->pid)
1041 extern "C" {
1042 static void __stdcall
1043 reset_signal_arrived () __attribute__ ((unused));
1044 static void __stdcall
1045 reset_signal_arrived ()
1046 {
1047   (void) ResetEvent (signal_arrived);
1048   sigproc_printf ("reset signal_arrived");
1049 }
1050
1051 void unused_sig_wrapper()
1052 {
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. */
1057 __asm__ volatile ("
1058         .text
1059         .globl  __raise
1060 __raise:
1061         pushl   %%ebp
1062         movl    %%esp,%%ebp
1063         movl    8(%%ebp),%%eax
1064         pushl   %%eax
1065         movl    $_myself,%%eax
1066         pushl   %6(%%eax)
1067         call    __kill
1068         mov     %%ebp,%%esp
1069         popl    %%ebp
1070         ret
1071
1072 _sigreturn:
1073         addl    $4,%%esp
1074         call    _set_process_mask@4
1075         popl    %%eax           # saved errno
1076         testl   %%eax,%%eax     # Is it < 0
1077         jl      1f              # yup.  ignore it
1078         movl    %1,%%ebx
1079         movl    %%eax,(%%ebx)
1080 1:      popl    %%eax
1081         popl    %%ebx
1082         popl    %%ecx
1083         popl    %%edx
1084         popl    %%edi
1085         popl    %%esi
1086         popf
1087         ret
1088
1089 _sigdelayed:
1090         pushl   %2      # original return address
1091         pushf
1092         pushl   %%esi
1093         pushl   %%edi
1094         pushl   %%edx
1095         pushl   %%ecx
1096         pushl   %%ebx
1097         pushl   %%eax
1098         pushl   %7      # saved errno
1099         pushl   %3      # oldmask
1100         pushl   %4      # signal argument
1101         pushl   $_sigreturn
1102
1103         call    _reset_signal_arrived@0
1104         movl    $0,%0
1105
1106         cmpl    $0,_pending_signals
1107         je      2f
1108 ___sigfirst:
1109         pushl   $0
1110         call    _sig_dispatch_pending@4
1111 ___siglast:
1112
1113 2:      jmp     *%5
1114
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)
1118   );
1119 }
1120 }