OSDN Git Service

* cygtls.cc (_cygtls::handle_threadlist_exception): Make an error fatal.
[pf3gnuchains/pf3gnuchains4x.git] / winsup / cygwin / exceptions.cc
1 /* exceptions.cc
2
3    Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
4    2005 Red Hat, Inc.
5
6 This file is part of Cygwin.
7
8 This software is a copyrighted work licensed under the terms of the
9 Cygwin license.  Please consult the file "CYGWIN_LICENSE" for
10 details. */
11
12 #include "winsup.h"
13 #include <wingdi.h>
14 #include <winuser.h>
15 #include <imagehlp.h>
16 #include <stdlib.h>
17 #include <setjmp.h>
18 #include <assert.h>
19
20 #include "exceptions.h"
21 #include "sync.h"
22 #include "pinfo.h"
23 #include "cygtls.h"
24 #include "sigproc.h"
25 #include "cygerrno.h"
26 #include "shared_info.h"
27 #include "perprocess.h"
28 #include "security.h"
29 #include "path.h"
30 #include "fhandler.h"
31 #include "dtable.h"
32 #include "cygheap.h"
33
34 #define CALL_HANDLER_RETRY 20
35
36 char debugger_command[2 * CYG_MAX_PATH + 20];
37
38 extern "C" {
39 extern void sigdelayed ();
40 };
41
42 extern NO_COPY DWORD dwExeced;
43 int NO_COPY sigExeced;
44
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;
49
50 /* This is set to indicate that we have already exited.  */
51
52 static NO_COPY int exit_already = 0;
53 static muto NO_COPY mask_sync;
54
55 NO_COPY static struct
56 {
57   unsigned int code;
58   const char *name;
59 } status_info[] =
60 {
61 #define X(s) s, #s
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) },
90   { 0, 0 }
91 #undef X
92 };
93
94 /* Initialization code.  */
95
96 BOOL WINAPI
97 dummy_ctrl_c_handler (DWORD dwCtrlType)
98 {
99   return TRUE;
100 }
101
102 void
103 init_console_handler (BOOL install_handler)
104 {
105   BOOL res;
106   while (SetConsoleCtrlHandler (ctrl_c_handler, FALSE))
107     continue;
108   if (install_handler)
109     res = SetConsoleCtrlHandler (ctrl_c_handler, TRUE);
110   else if (wincap.has_null_console_handler_routine ())
111     res = SetConsoleCtrlHandler (NULL, TRUE);
112   else
113     res = SetConsoleCtrlHandler (dummy_ctrl_c_handler, TRUE);
114   if (!res)
115     system_printf ("SetConsoleCtrlHandler failed, %E");
116 }
117
118 extern "C" void
119 error_start_init (const char *buf)
120 {
121   if (!buf || !*buf)
122     {
123       debugger_command[0] = '\0';
124       return;
125     }
126
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, '\\'))
131     *p = '/';
132
133   __small_sprintf (debugger_command, "%s \"%s\"", buf, pgm);
134 }
135
136 static void
137 open_stackdumpfile ()
138 {
139   if (myself->progname[0])
140     {
141       const char *p;
142       /* write to progname.stackdump if possible */
143       if (!myself->progname[0])
144         p = "unknown";
145       else if ((p = strrchr (myself->progname, '\\')))
146         p++;
147       else
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)
154         {
155           if (!myself->cygstarted)
156             system_printf ("Dumping stack trace to %s", corefile);
157           else
158             debug_printf ("Dumping stack trace to %s", corefile);
159           SetStdHandle (STD_ERROR_HANDLE, h);
160         }
161     }
162 }
163
164 /* Utilities for dumping the stack, etc.  */
165
166 static void
167 exception (EXCEPTION_RECORD *e,  CONTEXT *in)
168 {
169   const char *exception_name = NULL;
170
171   if (e)
172     {
173       for (int i = 0; status_info[i].name; i++)
174         {
175           if (status_info[i].code == e->ExceptionCode)
176             {
177               exception_name = status_info[i].name;
178               break;
179             }
180         }
181     }
182
183   if (exception_name)
184     small_printf ("Exception: %s at eip=%08x\r\n", exception_name, in->Eip);
185   else
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);
193 }
194
195 /* A class for manipulating the stack. */
196 class stack_info
197 {
198   int walk ();                  /* Uses the "old" method */
199   char *next_offset () {return *((char **) sf.AddrFrame.Offset);}
200   bool needargs;
201   DWORD dummy_frame;
202 public:
203   STACKFRAME sf;                 /* For storing the stack information */
204   void init (DWORD, bool, bool); /* Called the first time that stack info is needed */
205
206   /* Postfix ++ iterates over the stack, returning zero when nothing is left. */
207   int operator ++(int) { return walk (); }
208 };
209
210 /* The number of parameters used in STACKFRAME */
211 #define NPARAMS (sizeof (thestack.sf.Params) / sizeof (thestack.sf.Params[0]))
212
213 /* This is the main stack frame info for this process. */
214 static NO_COPY stack_info thestack;
215
216 /* Initialize everything needed to start iterating. */
217 void
218 stack_info::init (DWORD ebp, bool wantargs, bool goodframe)
219 {
220 # define debp ((DWORD *) ebp)
221   memset (&sf, 0, sizeof (sf));
222   if (!goodframe)
223     sf.AddrFrame.Offset = ebp;
224   else
225     {
226       dummy_frame = ebp;
227       sf.AddrFrame.Offset = (DWORD) &dummy_frame;
228     }
229   sf.AddrReturn.Offset = debp[1];
230   sf.AddrFrame.Mode = AddrModeFlat;
231   needargs = wantargs;
232 # undef debp
233 }
234
235 /* Walk the stack by looking at successive stored 'bp' frames.
236    This is not foolproof. */
237 int
238 stack_info::walk ()
239 {
240   char **ebp;
241   if ((ebp = (char **) next_offset ()) == NULL)
242     return 0;
243
244   sf.AddrFrame.Offset = (DWORD) ebp;
245   sf.AddrPC.Offset = sf.AddrReturn.Offset;
246
247   if (!sf.AddrPC.Offset)
248     return 0;           /* stack frames are exhausted */
249
250   /* The return address always follows the stack pointer */
251   sf.AddrReturn.Offset = (DWORD) *++ebp;
252
253   if (needargs)
254     /* The arguments follow the return address */
255     for (unsigned i = 0; i < NPARAMS; i++)
256       sf.Params[i] = (DWORD) *++ebp;
257
258   return 1;
259 }
260
261 static void
262 stackdump (DWORD ebp, int open_file, bool isexception)
263 {
264   extern unsigned long rlim_core;
265
266   if (rlim_core == 0UL)
267     return;
268
269   if (open_file)
270     open_stackdumpfile ();
271
272   int i;
273
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++)
277     {
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");
283     }
284   small_printf ("End of stack trace%s\n",
285               i == 16 ? " (more stack frames may be present)" : "");
286 }
287
288 /* Temporary (?) function for external callers to get a stack dump */
289 extern "C" void
290 cygwin_stackdump ()
291 {
292   CONTEXT c;
293   c.ContextFlags = CONTEXT_FULL;
294   GetThreadContext (GetCurrentThread (), &c);
295   stackdump (c.Ebp, 0, 0);
296 }
297
298 #define TIME_TO_WAIT_FOR_DEBUGGER 10000
299
300 extern "C" int
301 try_to_debug (bool waitloop)
302 {
303   debug_printf ("debugger_command '%s'", debugger_command);
304   if (*debugger_command == '\0')
305     return 0;
306   if (being_debugged ())
307     {
308       DebugBreak ();
309       return 0;
310     }
311
312   __small_sprintf (strchr (debugger_command, '\0'), " %u", GetCurrentProcessId ());
313
314   LONG prio = GetThreadPriority (GetCurrentThread ());
315   SetThreadPriority (GetCurrentThread (), THREAD_PRIORITY_HIGHEST);
316   PROCESS_INFORMATION pi = {NULL, 0, 0, 0};
317
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;
320   si.lpDesktop = NULL;
321   si.dwFlags = 0;
322   si.cb = sizeof (si);
323
324   /* FIXME: need to know handles of all running threads to
325      suspend_all_threads_except (current_thread_id);
326   */
327
328   /* if any of these mutexes is owned, we will fail to start any cygwin app
329      until trapped app exits */
330
331   ReleaseMutex (tty_mutex);
332
333   /* prevent recursive exception handling */
334   char* rawenv = GetEnvironmentStrings () ;
335   for (char* p = rawenv; *p != '\0'; p = strchr (p, '\0') + 1)
336     {
337       if (strncmp (p, "CYGWIN=", strlen ("CYGWIN=")) == 0)
338         {
339           char* q = strstr (p, "error_start") ;
340           /* replace 'error_start=...' with '_rror_start=...' */
341           if (q)
342             {
343               *q = '_' ;
344               SetEnvironmentVariable ("CYGWIN", p + strlen ("CYGWIN=")) ;
345             }
346           break ;
347         }
348     }
349
350   console_printf ("*** starting debugger for pid %u, tid %u\n",
351                   cygwin_pid (GetCurrentProcessId ()), GetCurrentThreadId ());
352   BOOL dbg;
353   dbg = CreateProcess (NULL,
354                        debugger_command,
355                        NULL,
356                        NULL,
357                        FALSE,
358                        CREATE_NEW_CONSOLE | CREATE_NEW_PROCESS_GROUP,
359                        NULL,
360                        NULL,
361                        &si,
362                        &pi);
363
364   if (!dbg)
365     system_printf ("Failed to start debugger, %E");
366   else
367     {
368       if (!waitloop)
369         return dbg;
370       SetThreadPriority (GetCurrentThread (), THREAD_PRIORITY_IDLE);
371       while (!being_debugged ())
372         low_priority_sleep (0);
373       Sleep (2000);
374     }
375
376   console_printf ("*** continuing pid %u from debugger call (%d)\n",
377                   cygwin_pid (GetCurrentProcessId ()), dbg);
378
379   SetThreadPriority (GetCurrentThread (), prio);
380   return dbg;
381 }
382
383 extern "C" DWORD __stdcall RtlUnwind (void *, void *, void *, DWORD);
384 static void __stdcall rtl_unwind (exception_list *, PEXCEPTION_RECORD) __attribute__ ((noinline, regparm (3)));
385 void __stdcall
386 rtl_unwind (exception_list *frame, PEXCEPTION_RECORD e)
387 {
388   __asm__ ("\n\
389   pushl         %%ebx                                   \n\
390   pushl         %%edi                                   \n\
391   pushl         %%esi                                   \n\
392   pushl         $0                                      \n\
393   pushl         %1                                      \n\
394   pushl         $1f                                     \n\
395   pushl         %0                                      \n\
396   call          _RtlUnwind@16                           \n\
397 1:                                                      \n\
398   popl          %%esi                                   \n\
399   popl          %%edi                                   \n\
400   popl          %%ebx                                   \n\
401 ": : "r" (frame), "r" (e));
402 }
403
404 /* Main exception handler. */
405
406 int
407 _cygtls::handle_exceptions (EXCEPTION_RECORD *e, exception_list *frame, CONTEXT *in, void *)
408 {
409   static bool NO_COPY debugging;
410   static int NO_COPY recursed;
411   _cygtls& me = _my_tls;
412
413   if (debugging && ++debugging < 500000)
414     {
415       SetThreadPriority (hMainThread, THREAD_PRIORITY_NORMAL);
416       return 0;
417     }
418
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)
422     return 1;
423
424   siginfo_t si;
425   si.si_code = SI_KERNEL;
426   /* Coerce win32 value to posix value.  */
427   switch (e->ExceptionCode)
428     {
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;
435       break;
436     case STATUS_FLOAT_INEXACT_RESULT:
437       si.si_signo = SIGFPE;
438       si.si_code = FPE_FLTRES;
439       break;
440     case STATUS_FLOAT_OVERFLOW:
441       si.si_signo = SIGFPE;
442       si.si_code = FPE_FLTOVF;
443       break;
444     case STATUS_FLOAT_UNDERFLOW:
445       si.si_signo = SIGFPE;
446       si.si_code = FPE_FLTUND;
447       break;
448     case STATUS_INTEGER_DIVIDE_BY_ZERO:
449       si.si_signo = SIGFPE;
450       si.si_code = FPE_INTDIV;
451       break;
452     case STATUS_INTEGER_OVERFLOW:
453       si.si_signo = SIGFPE;
454       si.si_code = FPE_INTOVF;
455       break;
456
457     case STATUS_ILLEGAL_INSTRUCTION:
458       si.si_signo = SIGILL;
459       si.si_code = ILL_ILLOPC;
460       break;
461
462     case STATUS_PRIVILEGED_INSTRUCTION:
463       si.si_signo = SIGILL;
464       si.si_code = ILL_PRVOPC;
465       break;
466
467     case STATUS_NONCONTINUABLE_EXCEPTION:
468       si.si_signo = SIGILL;
469       si.si_code = ILL_ILLADR;
470       break;
471
472     case STATUS_TIMEOUT:
473       si.si_signo = SIGALRM;
474       break;
475
476     case STATUS_GUARD_PAGE_VIOLATION:
477       si.si_signo = SIGBUS;
478       si.si_code = BUS_OBJERR;
479       break;
480
481     case STATUS_ACCESS_VIOLATION:
482       if (mmap_is_attached_page (e->ExceptionInformation[1]))
483         {
484           si.si_signo = SIGBUS;
485           si.si_code = BUS_OBJERR;
486           break;
487         }
488       /*FALLTHRU*/
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;
497       break;
498
499     case STATUS_CONTROL_C_EXIT:
500       si.si_signo = SIGINT;
501       break;
502
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
508          handling.  */
509       return 0;
510
511     default:
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.  */
515       return 1;
516     }
517
518   rtl_unwind (frame, e);
519
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);
522
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);
526
527   debug_printf ("In cygwin_except_handler calling %p",
528                  global_sigs[si.si_signo].sa_handler);
529
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)
533       {
534         ebp -= 2;
535         break;
536       }
537
538   if (!me.fault_guarded ()
539       && (!cygwin_finished_initializing
540           || &me == _sig_tls
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))
544     {
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)
549             {
550               system_printf ("Exception: %s", status_info[i].name);
551               break;
552             }
553
554       /* Another exception could happen while tracing or while exiting.
555          Only do this once.  */
556       if (recursed++)
557         system_printf ("Error while dumping state (probably corrupted stack)");
558       else
559         {
560           if (try_to_debug (0))
561             {
562               debugging = true;
563               return 0;
564             }
565
566           open_stackdumpfile ();
567           exception (e, in);
568           stackdump ((DWORD) ebp, 0, 1);
569         }
570
571       signal_exit (0x80 | si.si_signo); // Flag signal + core dump
572     }
573
574   if (me.fault_guarded ())
575     me.return_from_fault ();
576
577   si.si_addr = (void *) in->Eip;
578   si.si_errno = si.si_pid = si.si_uid = 0;
579   me.incyg++;
580   sig_send (NULL, si, &me);     // Signal myself
581   me.incyg--;
582   e->ExceptionFlags = 0;
583   return 0;
584 }
585
586 /* Utilities to call a user supplied exception handler.  */
587
588 #define SIG_NONMASKABLE (SIGTOMASK (SIGKILL) | SIGTOMASK (SIGSTOP))
589
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.
596  */
597 int __stdcall
598 handle_sigsuspend (sigset_t tempmask)
599 {
600   if (&_my_tls != _main_tls)
601     {
602       cancelable_wait (signal_arrived, INFINITE, cw_cancel_self);
603       return -1;
604     }
605
606   sigset_t oldmask = myself->getsigmask ();     // Remember for restoration
607
608   set_signal_mask (tempmask, myself->getsigmask ());
609   sigproc_printf ("oldmask %p, newmask %p", oldmask, tempmask);
610
611   pthread_testcancel ();
612   cancelable_wait (signal_arrived, INFINITE);
613
614   set_sig_errno (EINTR);        // Per POSIX
615
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. */
619
620   _my_tls.deltamask |= SIG_NONMASKABLE;
621   _my_tls.oldmask = oldmask;    // Will be restored by signal handler
622   return -1;
623 }
624
625 extern DWORD exec_exit;         // Possible exit value for exec
626
627 extern "C" {
628 static void
629 sig_handle_tty_stop (int sig)
630 {
631   _my_tls.incyg = 1;
632   /* Silently ignore attempts to suspend if there is no accommodating
633      cygwin parent to deal with this behavior. */
634   if (!myself->cygstarted)
635     {
636       myself->process_state &= ~PID_STOPPED;
637       return;
638     }
639
640   myself->stopsig = sig;
641   myself->alert_parent (sig);
642   sigproc_printf ("process %d stopped by signal %d", myself->pid, sig);
643   HANDLE w4[2];
644   w4[0] = sigCONT;
645   w4[1] = signal_arrived;
646   switch (WaitForMultipleObjects (2, w4, TRUE, INFINITE))
647     {
648     case WAIT_OBJECT_0:
649     case WAIT_OBJECT_0 + 1:
650       reset_signal_arrived ();
651       myself->alert_parent (SIGCONT);
652       break;
653     default:
654       api_fatal ("WaitSingleObject failed, %E");
655       break;
656     }
657   _my_tls.incyg = 0;
658 }
659 }
660
661 bool
662 _cygtls::interrupt_now (CONTEXT *cx, int sig, void *handler,
663                         struct sigaction& siga)
664 {
665   int res;
666   bool interrupted;
667   MEMORY_BASIC_INFORMATION m;
668
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);
672
673   char *checkdir = (char *) alloca (windows_system_directory_length + 4);
674   memset (checkdir, 0, sizeof (checkdir));
675
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)
681     res = false;
682   else if (h == user_data->hmodule)
683     res = true;
684   else if (!GetModuleFileName (h, checkdir, windows_system_directory_length + 2))
685     res = false;
686   else
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);
690 # undef h
691
692   if (!res || (incyg || spinning || locked ()))
693     interrupted = false;
694   else
695     {
696       push ((__stack_t) cx->Eip);
697       interrupt_setup (sig, handler, siga);
698       cx->Eip = pop ();
699       SetThreadContext (*this, cx); /* Restart the thread in a new location */
700       interrupted = true;
701     }
702   return interrupted;
703 }
704
705 void __stdcall
706 _cygtls::interrupt_setup (int sig, void *handler, struct sigaction& siga)
707 {
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)
714     {
715       myself->stopsig = 0;
716       myself->process_state |= PID_STOPPED;
717     }
718
719   this->sig = sig;                      // Should always be last thing set to avoid a race
720
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,
725                   sig, res);
726 }
727
728 extern "C" void __stdcall
729 set_sig_errno (int e)
730 {
731   *_my_tls.errno_addr = e;
732   _my_tls.saved_errno = e;
733   // sigproc_printf ("errno %d", e);
734 }
735
736 static int setup_handler (int, void *, struct sigaction&, _cygtls *tls)
737   __attribute__((regparm(3)));
738 static int
739 setup_handler (int sig, void *handler, struct sigaction& siga, _cygtls *tls)
740 {
741   CONTEXT cx;
742   bool interrupted = false;
743
744   if (tls->sig)
745     {
746       sigproc_printf ("trying to send sig %d but signal %d already armed",
747                       sig, tls->sig);
748       goto out;
749     }
750
751   for (int i = 0; i < CALL_HANDLER_RETRY; i++)
752     {
753       tls->lock ();
754       if (tls->incyg)
755         {
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);
759           interrupted = true;
760           tls->unlock ();
761           break;
762         }
763
764       tls->unlock ();
765       DWORD res;
766       HANDLE hth = (HANDLE) *tls;
767
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
773          noticeable delays?
774          If the thread is already suspended (which can occur when a program has called
775          SuspendThread on itself) then just queue the signal. */
776
777 #ifndef DEBUGGING
778       sigproc_printf ("suspending mainthread");
779 #else
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);
784 #endif
785       res = SuspendThread (hth);
786       /* Just set pending if thread is already suspended */
787       if (res)
788         {
789           ResumeThread (hth);
790           break;
791         }
792       cx.ContextFlags = CONTEXT_CONTROL | CONTEXT_INTEGER;
793       if (!GetThreadContext (hth, &cx))
794         system_printf ("couldn't get context of main thread, %E");
795       else
796         interrupted = tls->interrupt_now (&cx, sig, handler, siga);
797
798       res = ResumeThread (hth);
799       if (interrupted)
800         break;
801
802       sigproc_printf ("couldn't interrupt.  trying again.");
803       low_priority_sleep (0);
804     }
805
806 out:
807   if (interrupted && tls->event)
808     {
809       HANDLE h = tls->event;
810       tls->event = NULL;
811       SetEvent (h);
812     }
813   sigproc_printf ("signal %d %sdelivered", sig, interrupted ? "" : "not ");
814   return interrupted;
815 }
816
817 static inline bool
818 has_visible_window_station ()
819 {
820   HWINSTA station_hdl;
821   USEROBJECTFLAGS uof;
822   DWORD len;
823
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,
832                                     sizeof uof, &len)
833       && (uof.dwFlags & WSF_VISIBLE))
834     return true;
835   return false;
836 }
837
838 /* Keyboard interrupt handler.  */
839 static BOOL WINAPI
840 ctrl_c_handler (DWORD type)
841 {
842   static bool saw_close;
843
844   if (!cygwin_finished_initializing)
845     {
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);
850     }
851
852   _my_tls.remove (INFINITE);
853
854 #if 0
855   if (type == CTRL_C_EVENT || type == CTRL_BREAK_EVENT)
856     proc_subproc (PROC_KILLFORKED, 0);
857 #endif
858
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. */
862
863   if (type == CTRL_SHUTDOWN_EVENT)
864     {
865 #if 0
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
869          control message. */
870       sig_send (NULL, SIGTERM);
871 #endif
872       return FALSE;
873     }
874
875   if (myself->ctty != -1)
876     {
877       if (type == CTRL_CLOSE_EVENT)
878         {
879           sig_send (NULL, SIGHUP);
880           saw_close = true;
881           return FALSE;
882         }
883       if (!saw_close && type == CTRL_LOGOFF_EVENT)
884         {
885 #if 0
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. */
897
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);
903 #endif
904           return FALSE;
905         }
906     }
907
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))
911     return TRUE;
912
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 ())))
916     return TRUE;
917
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. */
926     {
927       int sig = SIGINT;
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)
931         sig = SIGQUIT;
932       t->last_ctrl_c = GetTickCount ();
933       killsys (-myself->pid, sig);
934       t->last_ctrl_c = GetTickCount ();
935       return TRUE;
936     }
937
938   return TRUE;
939 }
940
941 /* Function used by low level sig wrappers. */
942 extern "C" void __stdcall
943 set_process_mask (sigset_t newmask)
944 {
945   set_signal_mask (newmask, myself->getsigmask ());
946 sigproc_printf ("mask now %p\n", myself->getsigmask ());
947 }
948
949 extern "C" int
950 sighold (int sig)
951 {
952   /* check that sig is in right range */
953   if (sig < 0 || sig >= NSIG)
954     {
955       set_errno (EINVAL);
956       syscall_printf ("signal %d out of range", sig);
957       return -1;
958     }
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 ();
964   return 0;
965 }
966
967 extern "C" int
968 sigrelse (int sig)
969 {
970   /* check that sig is in right range */
971   if (sig < 0 || sig >= NSIG)
972     {
973       set_errno (EINVAL);
974       syscall_printf ("signal %d out of range", sig);
975       return -1;
976     }
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 ();
982   return 0;
983 }
984
985 /* Update the signal mask for this process and return the old mask.
986    Called from sigdelayed */
987 extern "C" sigset_t
988 set_process_mask_delta ()
989 {
990   mask_sync.acquire (INFINITE);
991   sigset_t newmask, oldmask;
992
993   if (_my_tls.deltamask & SIG_NONMASKABLE)
994     oldmask = _my_tls.oldmask; /* from handle_sigsuspend */
995   else
996     oldmask = myself->getsigmask ();
997   newmask = (oldmask | _my_tls.deltamask) & ~SIG_NONMASKABLE;
998   sigproc_printf ("oldmask %p, newmask %p, deltamask %p", oldmask, newmask,
999                   _my_tls.deltamask);
1000   myself->setsigmask (newmask);
1001   mask_sync.release ();
1002   return oldmask;
1003 }
1004
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)
1009 {
1010 #ifdef CGF
1011   if (&_my_tls == _sig_tls)
1012     small_printf ("********* waiting in signal thread\n");
1013 #endif
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,
1018                   mask_bits);
1019   oldmask = newmask;
1020   if (mask_bits)
1021     sig_dispatch_pending (true);
1022   else
1023     sigproc_printf ("not calling sig_dispatch_pending");
1024   mask_sync.release ();
1025 }
1026
1027 int __stdcall
1028 sigpacket::process ()
1029 {
1030   DWORD continue_now;
1031   if (si.si_signo != SIGCONT)
1032     continue_now = false;
1033   else
1034     {
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);
1043     }
1044
1045   int rc = 1;
1046
1047   sigproc_printf ("signal %d processing", si.si_signo);
1048   struct sigaction thissig = global_sigs[si.si_signo];
1049
1050   myself->rusage_self.ru_nsignals++;
1051
1052   bool masked;
1053   void *handler;
1054   if (!hExeced || (void *) thissig.sa_handler == (void *) SIG_IGN)
1055     handler = (void *) thissig.sa_handler;
1056   else if (tls)
1057     return 1;
1058   else
1059     handler = NULL;
1060
1061   if (si.si_signo == SIGKILL)
1062     goto exit_sig;
1063   if (si.si_signo == SIGSTOP)
1064     {
1065       sig_clear (SIGCONT);
1066       if (!tls)
1067         tls = _main_tls;
1068       goto stop;
1069     }
1070
1071   bool insigwait_mask;
1072   if ((masked = ISSTATE (myself, PID_STOPPED)))
1073     insigwait_mask = false;
1074   else if (!tls)
1075     insigwait_mask = !handler && (tls = _cygtls::find_tls (si.si_signo));
1076   else
1077     insigwait_mask = sigismember (&tls->sigwait_mask, si.si_signo);
1078
1079   if (insigwait_mask)
1080     goto thread_specific;
1081
1082   if (masked)
1083     /* nothing to do */;
1084   else if (sigismember (mask, si.si_signo))
1085     masked = true;
1086   else if (tls)
1087     masked  = sigismember (&tls->sigmask, si.si_signo);
1088
1089   if (!tls)
1090     tls = _main_tls;
1091
1092   if (masked)
1093     {
1094       sigproc_printf ("signal %d blocked", si.si_signo);
1095       rc = -1;
1096       goto done;
1097     }
1098
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);
1102
1103 #ifdef CGF
1104   if (being_debugged ())
1105     {
1106       char sigmsg[sizeof (_CYGWIN_SIGNAL_STRING " 0xffffffff")];
1107       __small_sprintf (sigmsg, _CYGWIN_SIGNAL_STRING " %p", si.si_signo);
1108       OutputDebugString (sigmsg);
1109     }
1110 #endif
1111
1112   if (handler == (void *) SIG_DFL)
1113     {
1114       if (insigwait_mask)
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)
1118         {
1119           sigproc_printf ("default signal %d ignored", si.si_signo);
1120           if (continue_now)
1121             SetEvent (signal_arrived);
1122           goto done;
1123         }
1124
1125       if (si.si_signo == SIGTSTP || si.si_signo == SIGTTIN || si.si_signo == SIGTTOU)
1126         goto stop;
1127
1128       goto exit_sig;
1129     }
1130
1131   if (handler == (void *) SIG_IGN)
1132     {
1133       sigproc_printf ("signal %d ignored", si.si_signo);
1134       goto done;
1135     }
1136
1137   if (handler == (void *) SIG_ERR)
1138     goto exit_sig;
1139
1140   tls->set_siginfo (this);
1141   goto dosig;
1142
1143 stop:
1144   /* Eat multiple attempts to STOP */
1145   if (ISSTATE (myself, PID_STOPPED))
1146     goto done;
1147   handler = (void *) sig_handle_tty_stop;
1148   thissig = global_sigs[SIGSTOP];
1149
1150 dosig:
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);
1154
1155 done:
1156   if (continue_now)
1157     SetEvent (sigCONT);
1158   sigproc_printf ("returning %d", rc);
1159   return rc;
1160
1161 thread_specific:
1162   tls->sig = si.si_signo;
1163   tls->set_siginfo (this);
1164   sigproc_printf ("releasing sigwait for thread");
1165   SetEvent (tls->event);
1166   goto done;
1167
1168 exit_sig:
1169   if (si.si_signo == SIGQUIT || si.si_signo == SIGABRT)
1170     {
1171       CONTEXT c;
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;
1177     }
1178   sigproc_printf ("signal %d, about to call do_exit", si.si_signo);
1179   signal_exit (si.si_signo);    /* never returns */
1180 }
1181
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
1184    routines to run.  */
1185 static void
1186 signal_exit (int rc)
1187 {
1188   if (hExeced)
1189     {
1190       sigproc_printf ("terminating captive process");
1191       TerminateProcess (hExeced, sigExeced = rc);
1192     }
1193
1194   lock_process until_exit (true);
1195   if (hExeced || exit_state)
1196     myself.exit (rc);
1197
1198   /* Starve other threads in a vain attempt to stop them from doing something
1199      stupid. */
1200   SetThreadPriority (GetCurrentThread (), THREAD_PRIORITY_TIME_CRITICAL);
1201
1202   user_data->resourcelocks->Delete ();
1203   user_data->resourcelocks->Init ();
1204
1205   sigproc_printf ("about to call do_exit (%x)", rc);
1206   SetEvent (signal_arrived);
1207   do_exit (rc);
1208 }
1209
1210 HANDLE NO_COPY tty_mutex = NULL;
1211
1212 void
1213 events_init ()
1214 {
1215   char *name;
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 */
1219
1220   if (!(tty_mutex = CreateMutex (&sec_all_nih, FALSE,
1221                                    name = shared_name (mutex_name,
1222                                                        "tty_mutex", 0))))
1223     api_fatal ("can't create title mutex '%s', %E", name);
1224
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] != '\\')
1233     {
1234       *end++ = '\\';
1235       *end = '\0';
1236     }
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);
1240 }
1241
1242 void
1243 events_terminate ()
1244 {
1245   exit_already = 1;
1246 }
1247
1248 int
1249 _cygtls::call_signal_handler ()
1250 {
1251   int this_sa_flags = 0;
1252   /* Call signal handler.  */
1253   while (sig)
1254     {
1255       lock ();
1256       this_sa_flags = sa_flags;
1257       int thissig = sig;
1258
1259       pop ();
1260       reset_signal_arrived ();
1261       sigset_t this_oldmask = set_process_mask_delta ();
1262       int this_errno = saved_errno;
1263       sig = 0;
1264       unlock ();        // make sure synchronized
1265       incyg = 0;
1266       if (!(this_sa_flags & SA_SIGINFO))
1267         {
1268           void (*sigfunc) (int) = func;
1269           sigfunc (thissig);
1270         }
1271       else
1272         {
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);
1277         }
1278       incyg = 1;
1279       set_signal_mask (this_oldmask, myself->getsigmask ());
1280       if (this_errno >= 0)
1281         set_errno (this_errno);
1282     }
1283
1284   return this_sa_flags & SA_RESTART;
1285 }
1286
1287 extern "C" void __stdcall
1288 reset_signal_arrived ()
1289 {
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]);
1295 }