OSDN Git Service

3fcd91c5eb841afa0f452454a6799cf9d0ec58c8
[pf3gnuchains/pf3gnuchains4x.git] / winsup / cygwin / exceptions.cc
1 /* exceptions.cc
2
3    Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
4    2005, 2006, 2007, 2008, 2009, 2010, 2011 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 #define CYGTLS_HANDLE
13 #include "winsup.h"
14 #include "miscfuncs.h"
15 #include <wingdi.h>
16 #include <winuser.h>
17 #include <imagehlp.h>
18 #include <stdlib.h>
19 #include <syslog.h>
20 #include <wchar.h>
21
22 #include "pinfo.h"
23 #include "cygtls.h"
24 #include "sigproc.h"
25 #include "shared_info.h"
26 #include "perprocess.h"
27 #include "path.h"
28 #include "fhandler.h"
29 #include "dtable.h"
30 #include "cygheap.h"
31 #include "child_info.h"
32 #include "ntdll.h"
33 #include "exception.h"
34
35 #define CALL_HANDLER_RETRY_OUTER 10
36 #define CALL_HANDLER_RETRY_INNER 10
37
38 char debugger_command[2 * NT_MAX_PATH + 20];
39
40 extern "C" {
41 extern void sigdelayed ();
42 };
43
44 static BOOL WINAPI ctrl_c_handler (DWORD);
45
46 /* This is set to indicate that we have already exited.  */
47
48 static NO_COPY int exit_already = 0;
49 static muto NO_COPY mask_sync;
50
51 NO_COPY static struct
52 {
53   unsigned int code;
54   const char *name;
55 } status_info[] =
56 {
57 #define X(s) s, #s
58   { X (STATUS_ABANDONED_WAIT_0) },
59   { X (STATUS_ACCESS_VIOLATION) },
60   { X (STATUS_ARRAY_BOUNDS_EXCEEDED) },
61   { X (STATUS_BREAKPOINT) },
62   { X (STATUS_CONTROL_C_EXIT) },
63   { X (STATUS_DATATYPE_MISALIGNMENT) },
64   { X (STATUS_FLOAT_DENORMAL_OPERAND) },
65   { X (STATUS_FLOAT_DIVIDE_BY_ZERO) },
66   { X (STATUS_FLOAT_INEXACT_RESULT) },
67   { X (STATUS_FLOAT_INVALID_OPERATION) },
68   { X (STATUS_FLOAT_OVERFLOW) },
69   { X (STATUS_FLOAT_STACK_CHECK) },
70   { X (STATUS_FLOAT_UNDERFLOW) },
71   { X (STATUS_GUARD_PAGE_VIOLATION) },
72   { X (STATUS_ILLEGAL_INSTRUCTION) },
73   { X (STATUS_INTEGER_DIVIDE_BY_ZERO) },
74   { X (STATUS_INTEGER_OVERFLOW) },
75   { X (STATUS_INVALID_DISPOSITION) },
76   { X (STATUS_IN_PAGE_ERROR) },
77   { X (STATUS_NONCONTINUABLE_EXCEPTION) },
78   { X (STATUS_NO_MEMORY) },
79   { X (STATUS_PENDING) },
80   { X (STATUS_PRIVILEGED_INSTRUCTION) },
81   { X (STATUS_SINGLE_STEP) },
82   { X (STATUS_STACK_OVERFLOW) },
83   { X (STATUS_TIMEOUT) },
84   { X (STATUS_USER_APC) },
85   { X (STATUS_WAIT_0) },
86   { 0, 0 }
87 #undef X
88 };
89
90 /* Initialization code.  */
91
92 void
93 init_console_handler (bool install_handler)
94 {
95   BOOL res;
96
97   SetConsoleCtrlHandler (ctrl_c_handler, FALSE);
98   SetConsoleCtrlHandler (NULL, FALSE);
99   if (install_handler)
100     res = SetConsoleCtrlHandler (ctrl_c_handler, TRUE);
101   else
102     res = SetConsoleCtrlHandler (NULL, TRUE);
103   if (!res)
104     system_printf ("SetConsoleCtrlHandler failed, %E");
105 }
106
107 extern "C" void
108 error_start_init (const char *buf)
109 {
110   if (!buf || !*buf)
111     {
112       debugger_command[0] = '\0';
113       return;
114     }
115
116   char pgm[NT_MAX_PATH];
117   if (!GetModuleFileName (NULL, pgm, NT_MAX_PATH))
118     strcpy (pgm, "cygwin1.dll");
119   for (char *p = strchr (pgm, '\\'); p; p = strchr (p, '\\'))
120     *p = '/';
121
122   __small_sprintf (debugger_command, "%s \"%s\"", buf, pgm);
123 }
124
125 static void
126 open_stackdumpfile ()
127 {
128   /* If we have no executable name, or if the CWD handle is NULL,
129      which means, the CWD is a virtual path, don't even try to open
130      a stackdump file. */
131   if (myself->progname[0] && cygheap->cwd.get_handle ())
132     {
133       const WCHAR *p;
134       /* write to progname.stackdump if possible */
135       if (!myself->progname[0])
136         p = L"unknown";
137       else if ((p = wcsrchr (myself->progname, L'\\')))
138         p++;
139       else
140         p = myself->progname;
141
142       WCHAR corefile[wcslen (p) + sizeof (".stackdump")];
143       wcpcpy (wcpcpy(corefile, p), L".stackdump");
144       UNICODE_STRING ucore;
145       OBJECT_ATTRIBUTES attr;
146       /* Create the UNICODE variation of <progname>.stackdump. */
147       RtlInitUnicodeString (&ucore, corefile);
148       /* Create an object attribute which refers to <progname>.stackdump
149          in Cygwin's cwd.  Stick to caseinsensitivity. */
150       InitializeObjectAttributes (&attr, &ucore, OBJ_CASE_INSENSITIVE,
151                                   cygheap->cwd.get_handle (), NULL);
152       HANDLE h;
153       IO_STATUS_BLOCK io;
154       NTSTATUS status;
155       /* Try to open it to dump the stack in it. */
156       status = NtCreateFile (&h, GENERIC_WRITE | SYNCHRONIZE, &attr, &io,
157                              NULL, FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
158                              FILE_SYNCHRONOUS_IO_NONALERT
159                              | FILE_OPEN_FOR_BACKUP_INTENT, NULL, 0);
160       if (NT_SUCCESS (status))
161         {
162           if (!myself->cygstarted)
163             system_printf ("Dumping stack trace to %S", &ucore);
164           else
165             debug_printf ("Dumping stack trace to %S", &ucore);
166           SetStdHandle (STD_ERROR_HANDLE, h);
167         }
168     }
169 }
170
171 /* Utilities for dumping the stack, etc.  */
172
173 static void
174 dump_exception (EXCEPTION_RECORD *e,  CONTEXT *in)
175 {
176   const char *exception_name = NULL;
177
178   if (e)
179     {
180       for (int i = 0; status_info[i].name; i++)
181         {
182           if (status_info[i].code == e->ExceptionCode)
183             {
184               exception_name = status_info[i].name;
185               break;
186             }
187         }
188     }
189
190   if (exception_name)
191     small_printf ("Exception: %s at eip=%08x\r\n", exception_name, in->Eip);
192   else
193     small_printf ("Signal %d at eip=%08x\r\n", e->ExceptionCode, in->Eip);
194   small_printf ("eax=%08x ebx=%08x ecx=%08x edx=%08x esi=%08x edi=%08x\r\n",
195                 in->Eax, in->Ebx, in->Ecx, in->Edx, in->Esi, in->Edi);
196   small_printf ("ebp=%08x esp=%08x program=%W, pid %u, thread %s\r\n",
197                 in->Ebp, in->Esp, myself->progname, myself->pid, cygthread::name ());
198   small_printf ("cs=%04x ds=%04x es=%04x fs=%04x gs=%04x ss=%04x\r\n",
199                 in->SegCs, in->SegDs, in->SegEs, in->SegFs, in->SegGs, in->SegSs);
200 }
201
202 /* A class for manipulating the stack. */
203 class stack_info
204 {
205   int walk ();                  /* Uses the "old" method */
206   char *next_offset () {return *((char **) sf.AddrFrame.Offset);}
207   bool needargs;
208   DWORD dummy_frame;
209 public:
210   STACKFRAME sf;                 /* For storing the stack information */
211   void init (DWORD, bool, bool); /* Called the first time that stack info is needed */
212
213   /* Postfix ++ iterates over the stack, returning zero when nothing is left. */
214   int operator ++(int) { return walk (); }
215 };
216
217 /* The number of parameters used in STACKFRAME */
218 #define NPARAMS (sizeof (thestack.sf.Params) / sizeof (thestack.sf.Params[0]))
219
220 /* This is the main stack frame info for this process. */
221 static NO_COPY stack_info thestack;
222
223 /* Initialize everything needed to start iterating. */
224 void
225 stack_info::init (DWORD ebp, bool wantargs, bool goodframe)
226 {
227 # define debp ((DWORD *) ebp)
228   memset (&sf, 0, sizeof (sf));
229   if (!goodframe)
230     sf.AddrFrame.Offset = ebp;
231   else
232     {
233       dummy_frame = ebp;
234       sf.AddrFrame.Offset = (DWORD) &dummy_frame;
235     }
236   sf.AddrReturn.Offset = debp[1];
237   sf.AddrFrame.Mode = AddrModeFlat;
238   needargs = wantargs;
239 # undef debp
240 }
241
242 extern "C" void _cygwin_exit_return ();
243
244 /* Walk the stack by looking at successive stored 'bp' frames.
245    This is not foolproof. */
246 int
247 stack_info::walk ()
248 {
249   char **ebp;
250
251   if ((void (*) ()) sf.AddrPC.Offset == _cygwin_exit_return)
252     return 0;           /* stack frames are exhausted */
253
254   if (((ebp = (char **) next_offset ()) == NULL) || (ebp >= (char **) cygwin_hmodule))
255     return 0;
256
257   sf.AddrFrame.Offset = (DWORD) ebp;
258   sf.AddrPC.Offset = sf.AddrReturn.Offset;
259
260   /* The return address always follows the stack pointer */
261   sf.AddrReturn.Offset = (DWORD) *++ebp;
262
263   if (needargs)
264     {
265       unsigned nparams = NPARAMS;
266
267       /* The arguments follow the return address */
268       sf.Params[0] = (DWORD) *++ebp;
269       /* Hack for XP/2K3 WOW64.  If the first stack param points to the
270          application entry point, we can only fetch one additional
271          parameter.  Accessing anything beyond this address results in
272          a SEGV.  This is fixed in Vista/2K8 WOW64. */
273       if (wincap.has_restricted_stack_args () && sf.Params[0] == 0x401000)
274         nparams = 2;
275       for (unsigned i = 1; i < nparams; i++)
276         sf.Params[i] = (DWORD) *++ebp;
277     }
278
279   return 1;
280 }
281
282 void
283 stackdump (DWORD ebp, int open_file, bool isexception)
284 {
285   static bool already_dumped;
286
287   if (cygheap->rlim_core == 0UL || (open_file && already_dumped))
288     return;
289
290   if (open_file)
291     open_stackdumpfile ();
292
293   already_dumped = true;
294
295   int i;
296
297   thestack.init (ebp, 1, !isexception); /* Initialize from the input CONTEXT */
298   small_printf ("Stack trace:\r\nFrame     Function  Args\r\n");
299   for (i = 0; i < 16 && thestack++; i++)
300     {
301       small_printf ("%08x  %08x ", thestack.sf.AddrFrame.Offset,
302                     thestack.sf.AddrPC.Offset);
303       for (unsigned j = 0; j < NPARAMS; j++)
304         small_printf ("%s%08x", j == 0 ? " (" : ", ", thestack.sf.Params[j]);
305       small_printf (")\r\n");
306     }
307   small_printf ("End of stack trace%s\n",
308               i == 16 ? " (more stack frames may be present)" : "");
309 }
310
311 bool
312 _cygtls::inside_kernel (CONTEXT *cx)
313 {
314   int res;
315   MEMORY_BASIC_INFORMATION m;
316
317   if (!isinitialized ())
318     return true;
319
320   memset (&m, 0, sizeof m);
321   if (!VirtualQuery ((LPCVOID) cx->Eip, &m, sizeof m))
322     sigproc_printf ("couldn't get memory info, pc %p, %E", cx->Eip);
323
324   size_t size = (windows_system_directory_length + 6) * sizeof (WCHAR);
325   PWCHAR checkdir = (PWCHAR) alloca (size);
326   memset (checkdir, 0, size);
327
328 # define h ((HMODULE) m.AllocationBase)
329   if (!h || m.State != MEM_COMMIT)      /* Be defensive */
330     res = true;
331   else if (h == user_data->hmodule)
332     res = false;
333   else if (!GetModuleFileNameW (h, checkdir, windows_system_directory_length + 6))
334     res = false;
335   else
336     {
337       /* Skip potential long path prefix. */
338       if (!wcsncmp (checkdir, L"\\\\?\\", 4))
339         checkdir += 4;
340       res = wcsncasecmp (windows_system_directory, checkdir,
341                          windows_system_directory_length) == 0;
342       if (!res && system_wow64_directory_length)
343         res = wcsncasecmp (system_wow64_directory, checkdir,
344                            system_wow64_directory_length) == 0;
345
346     }
347   sigproc_printf ("pc %p, h %p, inside_kernel %d", cx->Eip, h, res);
348 # undef h
349   return res;
350 }
351
352 /* Temporary (?) function for external callers to get a stack dump */
353 extern "C" void
354 cygwin_stackdump ()
355 {
356   CONTEXT c;
357   c.ContextFlags = CONTEXT_FULL;
358   GetThreadContext (GetCurrentThread (), &c);
359   stackdump (c.Ebp, 0, 0);
360 }
361
362 #define TIME_TO_WAIT_FOR_DEBUGGER 10000
363
364 extern "C" int
365 try_to_debug (bool waitloop)
366 {
367   debug_printf ("debugger_command '%s'", debugger_command);
368   if (*debugger_command == '\0')
369     return 0;
370   if (being_debugged ())
371     {
372       extern void break_here ();
373       break_here ();
374       return 0;
375     }
376
377   __small_sprintf (strchr (debugger_command, '\0'), " %u", GetCurrentProcessId ());
378
379   LONG prio = GetThreadPriority (GetCurrentThread ());
380   SetThreadPriority (GetCurrentThread (), THREAD_PRIORITY_HIGHEST);
381   PROCESS_INFORMATION pi = {NULL, 0, 0, 0};
382
383   STARTUPINFOW si = {0, NULL, NULL, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL};
384   si.lpReserved = NULL;
385   si.lpDesktop = NULL;
386   si.dwFlags = 0;
387   si.cb = sizeof (si);
388
389   /* FIXME: need to know handles of all running threads to
390      suspend_all_threads_except (current_thread_id);
391   */
392
393   /* If the tty mutex is owned, we will fail to start any cygwin app
394      until the trapped app exits.  However, this will only release any
395      the mutex if it is owned by this thread so that may be problematic. */
396
397   lock_ttys::release ();
398
399   /* prevent recursive exception handling */
400   PWCHAR rawenv = GetEnvironmentStringsW () ;
401   for (PWCHAR p = rawenv; *p != L'\0'; p = wcschr (p, L'\0') + 1)
402     {
403       if (wcsncmp (p, L"CYGWIN=", wcslen (L"CYGWIN=")) == 0)
404         {
405           PWCHAR q = wcsstr (p, L"error_start") ;
406           /* replace 'error_start=...' with '_rror_start=...' */
407           if (q)
408             {
409               *q = L'_' ;
410               SetEnvironmentVariableW (L"CYGWIN", p + wcslen (L"CYGWIN=")) ;
411             }
412           break ;
413         }
414     }
415
416   console_printf ("*** starting debugger for pid %u, tid %u\n",
417                   cygwin_pid (GetCurrentProcessId ()), GetCurrentThreadId ());
418   BOOL dbg;
419   WCHAR dbg_cmd[strlen(debugger_command)];
420   sys_mbstowcs (dbg_cmd, strlen(debugger_command) + 1, debugger_command);
421   dbg = CreateProcessW (NULL,
422                         dbg_cmd,
423                         NULL,
424                         NULL,
425                         FALSE,
426                         CREATE_NEW_CONSOLE | CREATE_NEW_PROCESS_GROUP,
427                         NULL,
428                         NULL,
429                         &si,
430                         &pi);
431
432   if (!dbg)
433     system_printf ("Failed to start debugger, %E");
434   else
435     {
436       if (!waitloop)
437         return dbg;
438       SetThreadPriority (GetCurrentThread (), THREAD_PRIORITY_IDLE);
439       while (!being_debugged ())
440         yield ();
441       Sleep (2000);
442     }
443
444   console_printf ("*** continuing pid %u from debugger call (%d)\n",
445                   cygwin_pid (GetCurrentProcessId ()), dbg);
446
447   SetThreadPriority (GetCurrentThread (), prio);
448   return dbg;
449 }
450
451 extern "C" DWORD __stdcall RtlUnwind (void *, void *, void *, DWORD);
452 static void __stdcall rtl_unwind (exception_list *, PEXCEPTION_RECORD) __attribute__ ((noinline, regparm (3)));
453 void __stdcall
454 rtl_unwind (exception_list *frame, PEXCEPTION_RECORD e)
455 {
456   __asm__ ("\n\
457   pushl         %%ebx                                   \n\
458   pushl         %%edi                                   \n\
459   pushl         %%esi                                   \n\
460   pushl         $0                                      \n\
461   pushl         %1                                      \n\
462   pushl         $1f                                     \n\
463   pushl         %0                                      \n\
464   call          _RtlUnwind@16                           \n\
465 1:                                                      \n\
466   popl          %%esi                                   \n\
467   popl          %%edi                                   \n\
468   popl          %%ebx                                   \n\
469 ": : "r" (frame), "r" (e));
470 }
471
472 /* Main exception handler. */
473
474 extern exception_list *_except_list asm ("%fs:0");
475
476 int
477 exception::handle (EXCEPTION_RECORD *e, exception_list *frame, CONTEXT *in, void *)
478 {
479   static bool NO_COPY debugging;
480   static int NO_COPY recursed;
481   _cygtls& me = _my_tls;
482
483   if (debugging && ++debugging < 500000)
484     {
485       SetThreadPriority (hMainThread, THREAD_PRIORITY_NORMAL);
486       return 0;
487     }
488
489   /* If we've already exited, don't do anything here.  Returning 1
490      tells Windows to keep looking for an exception handler.  */
491   if (exit_already || e->ExceptionFlags)
492     return 1;
493
494   siginfo_t si = {0};
495   si.si_code = SI_KERNEL;
496   /* Coerce win32 value to posix value.  */
497   switch (e->ExceptionCode)
498     {
499     case STATUS_FLOAT_DENORMAL_OPERAND:
500     case STATUS_FLOAT_DIVIDE_BY_ZERO:
501     case STATUS_FLOAT_INVALID_OPERATION:
502     case STATUS_FLOAT_STACK_CHECK:
503       si.si_signo = SIGFPE;
504       si.si_code = FPE_FLTSUB;
505       break;
506     case STATUS_FLOAT_INEXACT_RESULT:
507       si.si_signo = SIGFPE;
508       si.si_code = FPE_FLTRES;
509       break;
510     case STATUS_FLOAT_OVERFLOW:
511       si.si_signo = SIGFPE;
512       si.si_code = FPE_FLTOVF;
513       break;
514     case STATUS_FLOAT_UNDERFLOW:
515       si.si_signo = SIGFPE;
516       si.si_code = FPE_FLTUND;
517       break;
518     case STATUS_INTEGER_DIVIDE_BY_ZERO:
519       si.si_signo = SIGFPE;
520       si.si_code = FPE_INTDIV;
521       break;
522     case STATUS_INTEGER_OVERFLOW:
523       si.si_signo = SIGFPE;
524       si.si_code = FPE_INTOVF;
525       break;
526
527     case STATUS_ILLEGAL_INSTRUCTION:
528       si.si_signo = SIGILL;
529       si.si_code = ILL_ILLOPC;
530       break;
531
532     case STATUS_PRIVILEGED_INSTRUCTION:
533       si.si_signo = SIGILL;
534       si.si_code = ILL_PRVOPC;
535       break;
536
537     case STATUS_NONCONTINUABLE_EXCEPTION:
538       si.si_signo = SIGILL;
539       si.si_code = ILL_ILLADR;
540       break;
541
542     case STATUS_TIMEOUT:
543       si.si_signo = SIGALRM;
544       break;
545
546     case STATUS_GUARD_PAGE_VIOLATION:
547       si.si_signo = SIGBUS;
548       si.si_code = BUS_OBJERR;
549       break;
550
551     case STATUS_DATATYPE_MISALIGNMENT:
552       si.si_signo = SIGBUS;
553       si.si_code = BUS_ADRALN;
554       break;
555
556     case STATUS_ACCESS_VIOLATION:
557       switch (mmap_is_attached_or_noreserve ((void *)e->ExceptionInformation[1],
558                                              1))
559         {
560         case MMAP_NORESERVE_COMMITED:
561           return 0;
562         case MMAP_RAISE_SIGBUS: /* MAP_NORESERVE page, commit failed, or
563                                    access to mmap page beyond EOF. */
564           si.si_signo = SIGBUS;
565           si.si_code = BUS_OBJERR;
566           break;
567         default:
568           MEMORY_BASIC_INFORMATION m;
569           VirtualQuery ((PVOID) e->ExceptionInformation[1], &m, sizeof m);
570           si.si_signo = SIGSEGV;
571           si.si_code = m.State == MEM_FREE ? SEGV_MAPERR : SEGV_ACCERR;
572           break;
573         }
574       break;
575
576     case STATUS_ARRAY_BOUNDS_EXCEEDED:
577     case STATUS_IN_PAGE_ERROR:
578     case STATUS_NO_MEMORY:
579     case STATUS_INVALID_DISPOSITION:
580     case STATUS_STACK_OVERFLOW:
581       si.si_signo = SIGSEGV;
582       si.si_code = SEGV_MAPERR;
583       break;
584
585     case STATUS_CONTROL_C_EXIT:
586       si.si_signo = SIGINT;
587       break;
588
589     case STATUS_INVALID_HANDLE:
590       /* CloseHandle will throw this exception if it is given an
591          invalid handle.  We don't care about the exception; we just
592          want CloseHandle to return an error.  This can be revisited
593          if gcc ever supports Windows style structured exception
594          handling.  */
595       return 0;
596
597     default:
598       /* If we don't recognize the exception, we have to assume that
599          we are doing structured exception handling, and we let
600          something else handle it.  */
601       return 1;
602     }
603
604   debug_printf ("In cygwin_except_handler exception %p at %p sp %p", e->ExceptionCode, in->Eip, in->Esp);
605   debug_printf ("In cygwin_except_handler signal %d at %p", si.si_signo, in->Eip);
606
607   bool masked = !!(me.sigmask & SIGTOMASK (si.si_signo));
608   if (masked)
609     syscall_printf ("signal %d, masked %p", si.si_signo,
610                     global_sigs[si.si_signo].sa_mask);
611
612   debug_printf ("In cygwin_except_handler calling %p",
613                  global_sigs[si.si_signo].sa_handler);
614
615   DWORD *ebp = (DWORD *) in->Esp;
616   for (DWORD *bpend = (DWORD *) __builtin_frame_address (0); ebp > bpend; ebp--)
617     if (*ebp == in->SegCs && ebp[-1] == in->Eip)
618       {
619         ebp -= 2;
620         break;
621       }
622
623   if (me.andreas)
624     me.andreas->leave ();       /* Return from a "san" caught fault */
625
626   me.copy_context (in);
627
628   /* Temporarily replace windows top level SEH with our own handler.
629      We don't want any Windows magic kicking in.  This top level frame
630      will be removed automatically after our exception handler returns. */
631   _except_list->handler = handle;
632
633   if (masked
634       || &me == _sig_tls
635       || !cygwin_finished_initializing
636       || (void *) global_sigs[si.si_signo].sa_handler == (void *) SIG_DFL
637       || (void *) global_sigs[si.si_signo].sa_handler == (void *) SIG_IGN
638       || (void *) global_sigs[si.si_signo].sa_handler == (void *) SIG_ERR)
639     {
640       /* Print the exception to the console */
641       if (!myself->cygstarted)
642         for (int i = 0; status_info[i].name; i++)
643           if (status_info[i].code == e->ExceptionCode)
644             {
645               system_printf ("Exception: %s", status_info[i].name);
646               break;
647             }
648
649       /* Another exception could happen while tracing or while exiting.
650          Only do this once.  */
651       if (recursed++)
652         system_printf ("Error while dumping state (probably corrupted stack)");
653       else
654         {
655           if (try_to_debug (0))
656             {
657               debugging = true;
658               return 0;
659             }
660
661           rtl_unwind (frame, e);
662           if (cygheap->rlim_core > 0UL)
663             {
664               open_stackdumpfile ();
665               dump_exception (e, in);
666               stackdump ((DWORD) ebp, 0, 1);
667             }
668         }
669
670       if (e->ExceptionCode == STATUS_ACCESS_VIOLATION)
671         {
672           int error_code = 0;
673           if (si.si_code == SEGV_ACCERR)        /* Address present */
674             error_code |= 1;
675           if (e->ExceptionInformation[0])       /* Write access */
676             error_code |= 2;
677           if (!me.inside_kernel (in))           /* User space */
678             error_code |= 4;
679           klog (LOG_INFO, "%s[%d]: segfault at %08x rip %08x rsp %08x error %d",
680                           __progname, myself->pid,
681                           e->ExceptionInformation[1], in->Eip, in->Esp,
682                           ((in->Eip >= 0x61000000 && in->Eip < 0x61200000)
683                            ? 0 : 4) | (e->ExceptionInformation[0] << 1));
684         }
685
686       /* Flag signal + core dump */
687       me.signal_exit ((cygheap->rlim_core > 0UL ? 0x80 : 0) | si.si_signo);
688     }
689
690   si.si_addr =  (si.si_signo == SIGSEGV || si.si_signo == SIGBUS
691                  ? (void *) e->ExceptionInformation[1]
692                  : (void *) in->Eip);
693   si.si_errno = si.si_pid = si.si_uid = 0;
694   me.incyg++;
695   sig_send (NULL, si, &me);     // Signal myself
696   me.incyg--;
697   e->ExceptionFlags = 0;
698   return 0;
699 }
700
701 /* Utilities to call a user supplied exception handler.  */
702
703 #define SIG_NONMASKABLE (SIGTOMASK (SIGKILL) | SIGTOMASK (SIGSTOP))
704
705 /* Non-raceable sigsuspend
706  * Note: This implementation is based on the Single UNIX Specification
707  * man page.  This indicates that sigsuspend always returns -1 and that
708  * attempts to block unblockable signals will be silently ignored.
709  * This is counter to what appears to be documented in some UNIX
710  * man pages, e.g. Linux.
711  */
712 int __stdcall
713 handle_sigsuspend (sigset_t tempmask)
714 {
715   sigset_t oldmask = _my_tls.sigmask;   // Remember for restoration
716
717   set_signal_mask (tempmask, _my_tls.sigmask);
718   sigproc_printf ("oldmask %p, newmask %p", oldmask, tempmask);
719
720   pthread_testcancel ();
721   cancelable_wait (signal_arrived);
722
723   set_sig_errno (EINTR);        // Per POSIX
724
725   /* A signal dispatch function will have been added to our stack and will
726      be hit eventually.  Set the old mask to be restored when the signal
727      handler returns and indicate its presence by modifying deltamask. */
728
729   _my_tls.deltamask |= SIG_NONMASKABLE;
730   _my_tls.oldmask = oldmask;    // Will be restored by signal handler
731   return -1;
732 }
733
734 extern DWORD exec_exit;         // Possible exit value for exec
735
736 extern "C" {
737 static void
738 sig_handle_tty_stop (int sig)
739 {
740   _my_tls.incyg = 1;
741   /* Silently ignore attempts to suspend if there is no accommodating
742      cygwin parent to deal with this behavior. */
743   if (!myself->cygstarted)
744     {
745       myself->process_state &= ~PID_STOPPED;
746       return;
747     }
748
749   myself->stopsig = sig;
750   myself->alert_parent (sig);
751   sigproc_printf ("process %d stopped by signal %d", myself->pid, sig);
752   HANDLE w4[2];
753   w4[0] = sigCONT;
754   w4[1] = signal_arrived;
755   switch (WaitForMultipleObjects (2, w4, TRUE, INFINITE))
756     {
757     case WAIT_OBJECT_0:
758     case WAIT_OBJECT_0 + 1:
759       myself->stopsig = SIGCONT;
760       myself->alert_parent (SIGCONT);
761       break;
762     default:
763       api_fatal ("WaitSingleObject failed, %E");
764       break;
765     }
766   _my_tls.incyg = 0;
767 }
768 }
769
770 bool
771 _cygtls::interrupt_now (CONTEXT *cx, int sig, void *handler,
772                         struct sigaction& siga)
773 {
774   bool interrupted;
775
776   /* Delay the interrupt if we are
777      1) somehow inside the DLL
778      2) in _sigfe (spinning is true) and about to enter cygwin DLL
779      3) in a Windows DLL.  */
780   if (incyg || spinning || inside_kernel (cx))
781     interrupted = false;
782   else
783     {
784       push ((__stack_t) cx->Eip);
785       interrupt_setup (sig, handler, siga);
786       cx->Eip = pop ();
787       SetThreadContext (*this, cx); /* Restart the thread in a new location */
788       interrupted = true;
789     }
790   return interrupted;
791 }
792
793 void __stdcall
794 _cygtls::interrupt_setup (int sig, void *handler, struct sigaction& siga)
795 {
796   push ((__stack_t) sigdelayed);
797   deltamask = siga.sa_mask & ~SIG_NONMASKABLE;
798   sa_flags = siga.sa_flags;
799   func = (void (*) (int)) handler;
800   if (siga.sa_flags & SA_RESETHAND)
801     siga.sa_handler = SIG_DFL;
802   saved_errno = -1;             // Flag: no errno to save
803   if (handler == sig_handle_tty_stop)
804     {
805       myself->stopsig = 0;
806       myself->process_state |= PID_STOPPED;
807     }
808
809   this->sig = sig;                      // Should always be last thing set to avoid a race
810
811   if (!event)
812     threadkill = false;
813   else
814     {
815       HANDLE h = event;
816       event = NULL;
817       SetEvent (h);
818     }
819
820   /* Clear any waiting threads prior to dispatching to handler function */
821   int res = SetEvent (signal_arrived);  // For an EINTR case
822   proc_subproc (PROC_CLEARWAIT, 1);
823   sigproc_printf ("armed signal_arrived %p, signal %d, res %d", signal_arrived,
824                   sig, res);
825 }
826
827 extern "C" void __stdcall
828 set_sig_errno (int e)
829 {
830   *_my_tls.errno_addr = e;
831   _my_tls.saved_errno = e;
832 }
833
834 static int setup_handler (int, void *, struct sigaction&, _cygtls *tls)
835   __attribute__((regparm(3)));
836 static int
837 setup_handler (int sig, void *handler, struct sigaction& siga, _cygtls *tls)
838 {
839   CONTEXT cx;
840   bool interrupted = false;
841
842   if (tls->sig)
843     {
844       sigproc_printf ("trying to send signal %d but signal %d already armed",
845                       sig, tls->sig);
846       goto out;
847     }
848
849   for (int n = 0; n < CALL_HANDLER_RETRY_OUTER; n++)
850     {
851       for (int i = 0; i < CALL_HANDLER_RETRY_INNER; i++)
852         {
853           tls->lock ();
854           if (tls->incyg)
855             {
856               sigproc_printf ("controlled interrupt. stackptr %p, stack %p, stackptr[-1] %p",
857                               tls->stackptr, tls->stack, tls->stackptr[-1]);
858               tls->interrupt_setup (sig, handler, siga);
859               interrupted = true;
860               tls->unlock ();
861               goto out;
862             }
863
864           DWORD res;
865           HANDLE hth = (HANDLE) *tls;
866
867           /* Suspend the thread which will receive the signal.
868              If one of these conditions is not true we loop.
869              If the thread is already suspended (which can occur when a program
870              has called SuspendThread on itself) then just queue the signal. */
871
872           sigproc_printf ("suspending thread");
873           res = SuspendThread (hth);
874           /* Just set pending if thread is already suspended */
875           if (res)
876             {
877               ResumeThread (hth);
878               goto out;
879             }
880           cx.ContextFlags = CONTEXT_CONTROL | CONTEXT_INTEGER;
881           if (!GetThreadContext (hth, &cx))
882             system_printf ("couldn't get context of thread, %E");
883           else
884             interrupted = tls->interrupt_now (&cx, sig, handler, siga);
885
886           tls->unlock ();
887           res = ResumeThread (hth);
888           if (interrupted)
889             goto out;
890
891           sigproc_printf ("couldn't interrupt.  trying again.");
892           yield ();
893         }
894       /* Hit here if we couldn't deliver the signal.  Take a more drastic
895          action before trying again. */
896       Sleep (1);
897     }
898
899 out:
900   sigproc_printf ("signal %d %sdelivered", sig, interrupted ? "" : "not ");
901   return interrupted;
902 }
903
904 static inline bool
905 has_visible_window_station ()
906 {
907   HWINSTA station_hdl;
908   USEROBJECTFLAGS uof;
909   DWORD len;
910
911   /* Check if the process is associated with a visible window station.
912      These are processes running on the local desktop as well as processes
913      running in terminal server sessions.
914      Processes running in a service session not explicitely associated
915      with the desktop (using the "Allow service to interact with desktop"
916      property) are running in an invisible window station. */
917   if ((station_hdl = GetProcessWindowStation ())
918       && GetUserObjectInformationW (station_hdl, UOI_FLAGS, &uof,
919                                     sizeof uof, &len)
920       && (uof.dwFlags & WSF_VISIBLE))
921     return true;
922   return false;
923 }
924
925 /* Keyboard interrupt handler.  */
926 static BOOL WINAPI
927 ctrl_c_handler (DWORD type)
928 {
929   static bool saw_close;
930
931   if (!cygwin_finished_initializing)
932     {
933       if (myself->cygstarted)   /* Was this process created by a cygwin process? */
934         return TRUE;            /* Yes.  Let the parent eventually handle CTRL-C issues. */
935       debug_printf ("exiting with status %p", STATUS_CONTROL_C_EXIT);
936       ExitProcess (STATUS_CONTROL_C_EXIT);
937     }
938
939   /* Remove early or we could overthrow the threadlist in cygheap.
940      Deleting this line causes ash to SEGV if CTRL-C is hit repeatedly.
941      I am not exactly sure why that is.  Maybe it's just because this
942      adds some early serialization to ctrl_c_handler which prevents
943      multiple simultaneous calls? */
944   _my_tls.remove (INFINITE);
945
946 #if 0
947   if (type == CTRL_C_EVENT || type == CTRL_BREAK_EVENT)
948     proc_subproc (PROC_KILLFORKED, 0);
949 #endif
950
951   /* Return FALSE to prevent an "End task" dialog box from appearing
952      for each Cygwin process window that's open when the computer
953      is shut down or console window is closed. */
954
955   if (type == CTRL_SHUTDOWN_EVENT)
956     {
957 #if 0
958       /* Don't send a signal.  Only NT service applications and their child
959          processes will receive this event and the services typically already
960          handle the shutdown action when getting the SERVICE_CONTROL_SHUTDOWN
961          control message. */
962       sig_send (NULL, SIGTERM);
963 #endif
964       return FALSE;
965     }
966
967   if (myself->ctty != -1)
968     {
969       if (type == CTRL_CLOSE_EVENT)
970         {
971           sig_send (NULL, SIGHUP);
972           saw_close = true;
973           return FALSE;
974         }
975       if (!saw_close && type == CTRL_LOGOFF_EVENT)
976         {
977           /* The CTRL_LOGOFF_EVENT is sent when *any* user logs off.
978              The below code sends a SIGHUP only if it is not performing the
979              default activity for SIGHUP.  Note that it is possible for two
980              SIGHUP signals to arrive if a process group leader is exiting
981              too.  Getting this 100% right is saved for a future cygwin mailing
982              list goad.  */
983           if (global_sigs[SIGHUP].sa_handler != SIG_DFL)
984             {
985               sig_send (myself_nowait, SIGHUP);
986               return TRUE;
987             }
988           return FALSE;
989         }
990     }
991
992   if (ch_spawn.set_saw_ctrl_c ())
993     return TRUE;
994
995   /* We're only the process group leader when we have a valid pinfo structure.
996      If we don't have one, then the parent "stub" will handle the signal. */
997   if (!pinfo (cygwin_pid (GetCurrentProcessId ())))
998     return TRUE;
999
1000   tty_min *t = cygwin_shared->tty.get_cttyp ();
1001   /* Ignore this if we're not the process group leader since it should be handled
1002      *by* the process group leader. */
1003   if (t && t->getpgid () == myself->pid &&
1004        (GetTickCount () - t->last_ctrl_c) >= MIN_CTRL_C_SLOP)
1005     /* Otherwise we just send a SIGINT to the process group and return TRUE (to indicate
1006        that we have handled the signal).  At this point, type should be
1007        a CTRL_C_EVENT or CTRL_BREAK_EVENT. */
1008     {
1009       int sig = SIGINT;
1010       /* If intr and quit are both mapped to ^C, send SIGQUIT on ^BREAK */
1011       if (type == CTRL_BREAK_EVENT
1012           && t->ti.c_cc[VINTR] == 3 && t->ti.c_cc[VQUIT] == 3)
1013         sig = SIGQUIT;
1014       t->last_ctrl_c = GetTickCount ();
1015       killsys (-myself->pid, sig);
1016       t->last_ctrl_c = GetTickCount ();
1017       return TRUE;
1018     }
1019
1020   return TRUE;
1021 }
1022
1023 /* Function used by low level sig wrappers. */
1024 extern "C" void __stdcall
1025 set_process_mask (sigset_t newmask)
1026 {
1027   set_signal_mask (newmask, _my_tls.sigmask);
1028 }
1029
1030 extern "C" int
1031 sighold (int sig)
1032 {
1033   /* check that sig is in right range */
1034   if (sig < 0 || sig >= NSIG)
1035     {
1036       set_errno (EINVAL);
1037       syscall_printf ("signal %d out of range", sig);
1038       return -1;
1039     }
1040   mask_sync.acquire (INFINITE);
1041   sigset_t mask = _my_tls.sigmask;
1042   sigaddset (&mask, sig);
1043   set_signal_mask (mask, _my_tls.sigmask);
1044   mask_sync.release ();
1045   return 0;
1046 }
1047
1048 extern "C" int
1049 sigrelse (int sig)
1050 {
1051   /* check that sig is in right range */
1052   if (sig < 0 || sig >= NSIG)
1053     {
1054       set_errno (EINVAL);
1055       syscall_printf ("signal %d out of range", sig);
1056       return -1;
1057     }
1058   mask_sync.acquire (INFINITE);
1059   sigset_t mask = _my_tls.sigmask;
1060   sigdelset (&mask, sig);
1061   set_signal_mask (mask, _my_tls.sigmask);
1062   mask_sync.release ();
1063   return 0;
1064 }
1065
1066 extern "C" _sig_func_ptr
1067 sigset (int sig, _sig_func_ptr func)
1068 {
1069   sig_dispatch_pending ();
1070   _sig_func_ptr prev;
1071
1072   /* check that sig is in right range */
1073   if (sig < 0 || sig >= NSIG || sig == SIGKILL || sig == SIGSTOP)
1074     {
1075       set_errno (EINVAL);
1076       syscall_printf ("SIG_ERR = sigset (%d, %p)", sig, func);
1077       return (_sig_func_ptr) SIG_ERR;
1078     }
1079
1080   mask_sync.acquire (INFINITE);
1081   sigset_t mask = _my_tls.sigmask;
1082   /* If sig was in the signal mask return SIG_HOLD, otherwise return the
1083      previous disposition. */
1084   if (sigismember (&mask, sig))
1085     prev = SIG_HOLD;
1086   else
1087     prev = global_sigs[sig].sa_handler;
1088   /* If func is SIG_HOLD, add sig to the signal mask, otherwise set the
1089      disposition to func and remove sig from the signal mask. */
1090   if (func == SIG_HOLD)
1091     sigaddset (&mask, sig);
1092   else
1093     {
1094       /* No error checking.  The test which could return SIG_ERR has already
1095          been made above. */
1096       signal (sig, func);
1097       sigdelset (&mask, sig);
1098     }
1099   set_signal_mask (mask, _my_tls.sigmask);
1100   mask_sync.release ();
1101   return prev;
1102 }
1103
1104 extern "C" int
1105 sigignore (int sig)
1106 {
1107   return sigset (sig, SIG_IGN) == SIG_ERR ? -1 : 0;
1108 }
1109
1110 /* Update the signal mask for this process and return the old mask.
1111    Called from sigdelayed */
1112 extern "C" sigset_t
1113 set_process_mask_delta ()
1114 {
1115   mask_sync.acquire (INFINITE);
1116   sigset_t newmask, oldmask;
1117
1118   if (_my_tls.deltamask & SIG_NONMASKABLE)
1119     oldmask = _my_tls.oldmask; /* from handle_sigsuspend */
1120   else
1121     oldmask = _my_tls.sigmask;
1122   newmask = (oldmask | _my_tls.deltamask) & ~SIG_NONMASKABLE;
1123   sigproc_printf ("oldmask %p, newmask %p, deltamask %p", oldmask, newmask,
1124                   _my_tls.deltamask);
1125   _my_tls.sigmask = newmask;
1126   mask_sync.release ();
1127   return oldmask;
1128 }
1129
1130 /* Set the signal mask for this process.
1131    Note that some signals are unmaskable, as in UNIX.  */
1132 extern "C" void __stdcall
1133 set_signal_mask (sigset_t newmask, sigset_t& oldmask)
1134 {
1135 #ifdef CGF
1136   if (&_my_tls == _sig_tls)
1137     small_printf ("********* waiting in signal thread\n");
1138 #endif
1139   mask_sync.acquire (INFINITE);
1140   newmask &= ~SIG_NONMASKABLE;
1141   sigset_t mask_bits = oldmask & ~newmask;
1142   sigproc_printf ("oldmask %p, newmask %p, mask_bits %p", oldmask, newmask,
1143                   mask_bits);
1144   oldmask = newmask;
1145   if (mask_bits)
1146     sig_dispatch_pending (true);
1147   else
1148     sigproc_printf ("not calling sig_dispatch_pending");
1149   mask_sync.release ();
1150 }
1151
1152 int __stdcall
1153 sigpacket::process ()
1154 {
1155   DWORD continue_now;
1156   struct sigaction dummy = global_sigs[SIGSTOP];
1157
1158   if (si.si_signo != SIGCONT)
1159     continue_now = false;
1160   else
1161     {
1162       continue_now = myself->process_state & PID_STOPPED;
1163       myself->stopsig = 0;
1164       myself->process_state &= ~PID_STOPPED;
1165       /* Clear pending stop signals */
1166       sig_clear (SIGSTOP);
1167       sig_clear (SIGTSTP);
1168       sig_clear (SIGTTIN);
1169       sig_clear (SIGTTOU);
1170     }
1171
1172   switch (si.si_signo)
1173     {
1174     case SIGINT:
1175     case SIGQUIT:
1176     case SIGSTOP:
1177     case SIGTSTP:
1178       if (cygheap->ctty)
1179         cygheap->ctty->sigflush ();
1180       break;
1181     default:
1182       break;
1183     }
1184
1185   int rc = 1;
1186
1187   sigproc_printf ("signal %d processing", si.si_signo);
1188   struct sigaction& thissig = global_sigs[si.si_signo];
1189
1190   myself->rusage_self.ru_nsignals++;
1191
1192   bool masked;
1193   void *handler;
1194   if (!have_execed || (void *) thissig.sa_handler == (void *) SIG_IGN)
1195     handler = (void *) thissig.sa_handler;
1196   else if (tls)
1197     return 1;
1198   else
1199     handler = NULL;
1200
1201   _cygtls *use_tls = tls ?: _main_tls;
1202
1203   if (si.si_signo == SIGKILL)
1204     goto exit_sig;
1205   if (si.si_signo == SIGSTOP)
1206     {
1207       sig_clear (SIGCONT);
1208       goto stop;
1209     }
1210
1211   bool insigwait_mask;
1212   if ((masked = ISSTATE (myself, PID_STOPPED)))
1213     insigwait_mask = false;
1214   else if (tls)
1215     insigwait_mask = sigismember (&tls->sigwait_mask, si.si_signo);
1216   else if (!(tls = _cygtls::find_tls (si.si_signo)))
1217     insigwait_mask = false;
1218   else
1219     {
1220       use_tls = tls;
1221       insigwait_mask = true;
1222     }
1223
1224   if (insigwait_mask)
1225     goto thread_specific;
1226
1227   if (masked)
1228     /* nothing to do */;
1229   else if (sigismember (mask, si.si_signo))
1230     masked = true;
1231   else if (tls)
1232     masked  = sigismember (&tls->sigmask, si.si_signo);
1233
1234   if (masked)
1235     {
1236       sigproc_printf ("signal %d blocked", si.si_signo);
1237       rc = -1;
1238       goto done;
1239     }
1240
1241   /* Clear pending SIGCONT on stop signals */
1242   if (si.si_signo == SIGTSTP || si.si_signo == SIGTTIN || si.si_signo == SIGTTOU)
1243     sig_clear (SIGCONT);
1244
1245   if (handler == (void *) SIG_DFL)
1246     {
1247       if (insigwait_mask)
1248         goto thread_specific;
1249       if (si.si_signo == SIGCHLD || si.si_signo == SIGIO || si.si_signo == SIGCONT || si.si_signo == SIGWINCH
1250           || si.si_signo == SIGURG)
1251         {
1252           sigproc_printf ("default signal %d ignored", si.si_signo);
1253           if (continue_now)
1254             SetEvent (signal_arrived);
1255           goto done;
1256         }
1257
1258       if (si.si_signo == SIGTSTP || si.si_signo == SIGTTIN || si.si_signo == SIGTTOU)
1259         goto stop;
1260
1261       goto exit_sig;
1262     }
1263
1264   if (handler == (void *) SIG_IGN)
1265     {
1266       sigproc_printf ("signal %d ignored", si.si_signo);
1267       goto done;
1268     }
1269
1270   if (handler == (void *) SIG_ERR)
1271     goto exit_sig;
1272
1273   use_tls->set_siginfo (this);
1274   goto dosig;
1275
1276 stop:
1277   /* Eat multiple attempts to STOP */
1278   if (ISSTATE (myself, PID_STOPPED))
1279     goto done;
1280   handler = (void *) sig_handle_tty_stop;
1281   thissig = dummy;
1282
1283 dosig:
1284   /* Dispatch to the appropriate function. */
1285   sigproc_printf ("signal %d, about to call %p", si.si_signo, handler);
1286   rc = setup_handler (si.si_signo, handler, thissig, use_tls);
1287
1288 done:
1289   tls = use_tls;
1290   if (continue_now)
1291     SetEvent (sigCONT);
1292   sigproc_printf ("returning %d", rc);
1293   return rc;
1294
1295 thread_specific:
1296   use_tls->sig = si.si_signo;
1297   use_tls->set_siginfo (this);
1298   use_tls->func = NULL;
1299   sigproc_printf ("releasing sigwait for thread");
1300   SetEvent (use_tls->event);
1301   goto done;
1302
1303 exit_sig:
1304   use_tls->signal_exit (si.si_signo);   /* never returns */
1305 }
1306
1307 void
1308 events_init ()
1309 {
1310   mask_sync.init ("mask_sync");
1311 }
1312
1313 void
1314 events_terminate ()
1315 {
1316   exit_already = 1;
1317 }
1318
1319 int
1320 _cygtls::call_signal_handler ()
1321 {
1322   int this_sa_flags = SA_RESTART;
1323   while (1)
1324     {
1325       lock ();
1326       if (sig)
1327         pop ();
1328       else if (this != _main_tls)
1329         {
1330           _main_tls->lock ();
1331           if (_main_tls->sig && _main_tls->incyg)
1332             {
1333               paranoid_printf ("Redirecting to main_tls signal %d", _main_tls->sig);
1334               sig = _main_tls->sig;
1335               sa_flags = _main_tls->sa_flags;
1336               func = _main_tls->func;
1337               infodata = _main_tls->infodata;
1338               _main_tls->pop ();
1339               _main_tls->sig = 0;
1340
1341             }
1342           _main_tls->unlock ();
1343         }
1344       if (!sig)
1345         break;
1346
1347       debug_only_printf ("dealing with signal %d", sig);
1348       this_sa_flags = sa_flags;
1349       int thissig = sig;
1350       void (*thisfunc) (int) = func;
1351
1352       sigset_t this_oldmask = set_process_mask_delta ();
1353       int this_errno = saved_errno;
1354       sig = 0;
1355       unlock ();        // make sure synchronized
1356       if (!(this_sa_flags & SA_SIGINFO))
1357         {
1358           void (*sigfunc) (int) = thisfunc;
1359           incyg = false;
1360           sigfunc (thissig);
1361         }
1362       else
1363         {
1364           siginfo_t thissi = infodata;
1365           void (*sigact) (int, siginfo_t *, void *) = (void (*) (int, siginfo_t *, void *)) thisfunc;
1366           /* no ucontext_t information provided yet */
1367           incyg = false;
1368           sigact (thissig, &thissi, NULL);
1369         }
1370       incyg = true;
1371       set_signal_mask (this_oldmask, _my_tls.sigmask);
1372       if (this_errno >= 0)
1373         set_errno (this_errno);
1374     }
1375
1376   unlock ();
1377   return this_sa_flags & SA_RESTART || (this != _main_tls);
1378 }
1379
1380 void
1381 _cygtls::copy_context (CONTEXT *c)
1382 {
1383   memcpy (&thread_context, c, (&thread_context._internal - (unsigned char *) &thread_context));
1384 }
1385
1386 void
1387 _cygtls::signal_debugger (int sig)
1388 {
1389   if (isinitialized () && being_debugged ())
1390     {
1391       char sigmsg[2 * sizeof (_CYGWIN_SIGNAL_STRING " ffffffff ffffffff")];
1392       __small_sprintf (sigmsg, _CYGWIN_SIGNAL_STRING " %d %p %p", sig, thread_id, &thread_context);
1393       OutputDebugString (sigmsg);
1394     }
1395 }