OSDN Git Service

* path.cc (conv_path_list): Take cygwin_conv_path_t as third parameter.
[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   /* Apparently Windows 95 can sometimes return bogus addresses from
330      GetThreadContext.  These resolve to a strange allocation base.
331      These should *never* be treated as interruptible. */
332   if (!h || m.State != MEM_COMMIT)
333     res = true;
334   else if (h == user_data->hmodule)
335     res = false;
336   else if (!GetModuleFileNameW (h, checkdir, windows_system_directory_length + 6))
337     res = false;
338   else
339     {
340       /* Skip potential long path prefix. */
341       if (!wcsncmp (checkdir, L"\\\\?\\", 4))
342         checkdir += 4;
343       res = !wcsncasecmp (windows_system_directory, checkdir,
344                           windows_system_directory_length);
345     }
346   sigproc_printf ("pc %p, h %p, inside_kernel %d", cx->Eip, h, res);
347 # undef h
348   return res;
349 }
350
351 /* Temporary (?) function for external callers to get a stack dump */
352 extern "C" void
353 cygwin_stackdump ()
354 {
355   CONTEXT c;
356   c.ContextFlags = CONTEXT_FULL;
357   GetThreadContext (GetCurrentThread (), &c);
358   stackdump (c.Ebp, 0, 0);
359 }
360
361 #define TIME_TO_WAIT_FOR_DEBUGGER 10000
362
363 extern "C" int
364 try_to_debug (bool waitloop)
365 {
366   debug_printf ("debugger_command '%s'", debugger_command);
367   if (*debugger_command == '\0')
368     return 0;
369   if (being_debugged ())
370     {
371       extern void break_here ();
372       break_here ();
373       return 0;
374     }
375
376   __small_sprintf (strchr (debugger_command, '\0'), " %u", GetCurrentProcessId ());
377
378   LONG prio = GetThreadPriority (GetCurrentThread ());
379   SetThreadPriority (GetCurrentThread (), THREAD_PRIORITY_HIGHEST);
380   PROCESS_INFORMATION pi = {NULL, 0, 0, 0};
381
382   STARTUPINFOW si = {0, NULL, NULL, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL};
383   si.lpReserved = NULL;
384   si.lpDesktop = NULL;
385   si.dwFlags = 0;
386   si.cb = sizeof (si);
387
388   /* FIXME: need to know handles of all running threads to
389      suspend_all_threads_except (current_thread_id);
390   */
391
392   /* If the tty mutex is owned, we will fail to start any cygwin app
393      until the trapped app exits.  However, this will only release any
394      the mutex if it is owned by this thread so that may be problematic. */
395
396   lock_ttys::release ();
397
398   /* prevent recursive exception handling */
399   PWCHAR rawenv = GetEnvironmentStringsW () ;
400   for (PWCHAR p = rawenv; *p != L'\0'; p = wcschr (p, L'\0') + 1)
401     {
402       if (wcsncmp (p, L"CYGWIN=", wcslen (L"CYGWIN=")) == 0)
403         {
404           PWCHAR q = wcsstr (p, L"error_start") ;
405           /* replace 'error_start=...' with '_rror_start=...' */
406           if (q)
407             {
408               *q = L'_' ;
409               SetEnvironmentVariableW (L"CYGWIN", p + wcslen (L"CYGWIN=")) ;
410             }
411           break ;
412         }
413     }
414
415   console_printf ("*** starting debugger for pid %u, tid %u\n",
416                   cygwin_pid (GetCurrentProcessId ()), GetCurrentThreadId ());
417   BOOL dbg;
418   WCHAR dbg_cmd[strlen(debugger_command)];
419   sys_mbstowcs (dbg_cmd, strlen(debugger_command) + 1, debugger_command);
420   dbg = CreateProcessW (NULL,
421                         dbg_cmd,
422                         NULL,
423                         NULL,
424                         FALSE,
425                         CREATE_NEW_CONSOLE | CREATE_NEW_PROCESS_GROUP,
426                         NULL,
427                         NULL,
428                         &si,
429                         &pi);
430
431   if (!dbg)
432     system_printf ("Failed to start debugger, %E");
433   else
434     {
435       if (!waitloop)
436         return dbg;
437       SetThreadPriority (GetCurrentThread (), THREAD_PRIORITY_IDLE);
438       while (!being_debugged ())
439         yield ();
440       Sleep (2000);
441     }
442
443   console_printf ("*** continuing pid %u from debugger call (%d)\n",
444                   cygwin_pid (GetCurrentProcessId ()), dbg);
445
446   SetThreadPriority (GetCurrentThread (), prio);
447   return dbg;
448 }
449
450 extern "C" DWORD __stdcall RtlUnwind (void *, void *, void *, DWORD);
451 static void __stdcall rtl_unwind (exception_list *, PEXCEPTION_RECORD) __attribute__ ((noinline, regparm (3)));
452 void __stdcall
453 rtl_unwind (exception_list *frame, PEXCEPTION_RECORD e)
454 {
455   __asm__ ("\n\
456   pushl         %%ebx                                   \n\
457   pushl         %%edi                                   \n\
458   pushl         %%esi                                   \n\
459   pushl         $0                                      \n\
460   pushl         %1                                      \n\
461   pushl         $1f                                     \n\
462   pushl         %0                                      \n\
463   call          _RtlUnwind@16                           \n\
464 1:                                                      \n\
465   popl          %%esi                                   \n\
466   popl          %%edi                                   \n\
467   popl          %%ebx                                   \n\
468 ": : "r" (frame), "r" (e));
469 }
470
471 /* Main exception handler. */
472
473 extern exception_list *_except_list asm ("%fs:0");
474
475 int
476 exception::handle (EXCEPTION_RECORD *e, exception_list *frame, CONTEXT *in, void *)
477 {
478   static bool NO_COPY debugging;
479   static int NO_COPY recursed;
480   _cygtls& me = _my_tls;
481
482   if (debugging && ++debugging < 500000)
483     {
484       SetThreadPriority (hMainThread, THREAD_PRIORITY_NORMAL);
485       return 0;
486     }
487
488   /* If we've already exited, don't do anything here.  Returning 1
489      tells Windows to keep looking for an exception handler.  */
490   if (exit_already || e->ExceptionFlags)
491     return 1;
492
493   siginfo_t si = {0};
494   si.si_code = SI_KERNEL;
495   /* Coerce win32 value to posix value.  */
496   switch (e->ExceptionCode)
497     {
498     case STATUS_FLOAT_DENORMAL_OPERAND:
499     case STATUS_FLOAT_DIVIDE_BY_ZERO:
500     case STATUS_FLOAT_INVALID_OPERATION:
501     case STATUS_FLOAT_STACK_CHECK:
502       si.si_signo = SIGFPE;
503       si.si_code = FPE_FLTSUB;
504       break;
505     case STATUS_FLOAT_INEXACT_RESULT:
506       si.si_signo = SIGFPE;
507       si.si_code = FPE_FLTRES;
508       break;
509     case STATUS_FLOAT_OVERFLOW:
510       si.si_signo = SIGFPE;
511       si.si_code = FPE_FLTOVF;
512       break;
513     case STATUS_FLOAT_UNDERFLOW:
514       si.si_signo = SIGFPE;
515       si.si_code = FPE_FLTUND;
516       break;
517     case STATUS_INTEGER_DIVIDE_BY_ZERO:
518       si.si_signo = SIGFPE;
519       si.si_code = FPE_INTDIV;
520       break;
521     case STATUS_INTEGER_OVERFLOW:
522       si.si_signo = SIGFPE;
523       si.si_code = FPE_INTOVF;
524       break;
525
526     case STATUS_ILLEGAL_INSTRUCTION:
527       si.si_signo = SIGILL;
528       si.si_code = ILL_ILLOPC;
529       break;
530
531     case STATUS_PRIVILEGED_INSTRUCTION:
532       si.si_signo = SIGILL;
533       si.si_code = ILL_PRVOPC;
534       break;
535
536     case STATUS_NONCONTINUABLE_EXCEPTION:
537       si.si_signo = SIGILL;
538       si.si_code = ILL_ILLADR;
539       break;
540
541     case STATUS_TIMEOUT:
542       si.si_signo = SIGALRM;
543       break;
544
545     case STATUS_GUARD_PAGE_VIOLATION:
546       si.si_signo = SIGBUS;
547       si.si_code = BUS_OBJERR;
548       break;
549
550     case STATUS_DATATYPE_MISALIGNMENT:
551       si.si_signo = SIGBUS;
552       si.si_code = BUS_ADRALN;
553       break;
554
555     case STATUS_ACCESS_VIOLATION:
556       switch (mmap_is_attached_or_noreserve ((void *)e->ExceptionInformation[1],
557                                              1))
558         {
559         case MMAP_NORESERVE_COMMITED:
560           return 0;
561         case MMAP_RAISE_SIGBUS: /* MAP_NORESERVE page, commit failed, or
562                                    access to mmap page beyond EOF. */
563           si.si_signo = SIGBUS;
564           si.si_code = BUS_OBJERR;
565           break;
566         default:
567           MEMORY_BASIC_INFORMATION m;
568           VirtualQuery ((PVOID) e->ExceptionInformation[1], &m, sizeof m);
569           si.si_signo = SIGSEGV;
570           si.si_code = m.State == MEM_FREE ? SEGV_MAPERR : SEGV_ACCERR;
571           break;
572         }
573       break;
574
575     case STATUS_ARRAY_BOUNDS_EXCEEDED:
576     case STATUS_IN_PAGE_ERROR:
577     case STATUS_NO_MEMORY:
578     case STATUS_INVALID_DISPOSITION:
579     case STATUS_STACK_OVERFLOW:
580       si.si_signo = SIGSEGV;
581       si.si_code = SEGV_MAPERR;
582       break;
583
584     case STATUS_CONTROL_C_EXIT:
585       si.si_signo = SIGINT;
586       break;
587
588     case STATUS_INVALID_HANDLE:
589       /* CloseHandle will throw this exception if it is given an
590          invalid handle.  We don't care about the exception; we just
591          want CloseHandle to return an error.  This can be revisited
592          if gcc ever supports Windows style structured exception
593          handling.  */
594       return 0;
595
596     default:
597       /* If we don't recognize the exception, we have to assume that
598          we are doing structured exception handling, and we let
599          something else handle it.  */
600       return 1;
601     }
602
603   debug_printf ("In cygwin_except_handler exc %p at %p sp %p", e->ExceptionCode, in->Eip, in->Esp);
604   debug_printf ("In cygwin_except_handler signal %d at %p", si.si_signo, in->Eip);
605
606   bool masked = !!(me.sigmask & SIGTOMASK (si.si_signo));
607   if (masked)
608     syscall_printf ("signal %d, masked %p", si.si_signo,
609                     global_sigs[si.si_signo].sa_mask);
610
611   debug_printf ("In cygwin_except_handler calling %p",
612                  global_sigs[si.si_signo].sa_handler);
613
614   DWORD *ebp = (DWORD *) in->Esp;
615   for (DWORD *bpend = (DWORD *) __builtin_frame_address (0); ebp > bpend; ebp--)
616     if (*ebp == in->SegCs && ebp[-1] == in->Eip)
617       {
618         ebp -= 2;
619         break;
620       }
621
622   if (me.andreas)
623     me.andreas->leave ();       /* Return from a "san" caught fault */
624
625   me.copy_context (in);
626
627   /* Temporarily replace windows top level SEH with our own handler.
628      We don't want any Windows magic kicking in.  This top level frame
629      will be removed automatically after our exception handler returns. */
630   _except_list->handler = handle;
631
632   if (masked
633       || &me == _sig_tls
634       || !cygwin_finished_initializing
635       || (void *) global_sigs[si.si_signo].sa_handler == (void *) SIG_DFL
636       || (void *) global_sigs[si.si_signo].sa_handler == (void *) SIG_IGN
637       || (void *) global_sigs[si.si_signo].sa_handler == (void *) SIG_ERR)
638     {
639       /* Print the exception to the console */
640       if (!myself->cygstarted)
641         for (int i = 0; status_info[i].name; i++)
642           if (status_info[i].code == e->ExceptionCode)
643             {
644               system_printf ("Exception: %s", status_info[i].name);
645               break;
646             }
647
648       /* Another exception could happen while tracing or while exiting.
649          Only do this once.  */
650       if (recursed++)
651         system_printf ("Error while dumping state (probably corrupted stack)");
652       else
653         {
654           if (try_to_debug (0))
655             {
656               debugging = true;
657               return 0;
658             }
659
660           rtl_unwind (frame, e);
661           if (cygheap->rlim_core > 0UL)
662             {
663               open_stackdumpfile ();
664               dump_exception (e, in);
665               stackdump ((DWORD) ebp, 0, 1);
666             }
667         }
668
669       if (e->ExceptionCode == STATUS_ACCESS_VIOLATION)
670         {
671           int error_code = 0;
672           if (si.si_code == SEGV_ACCERR)        /* Address present */
673             error_code |= 1;
674           if (e->ExceptionInformation[0])       /* Write access */
675             error_code |= 2;
676           if (!me.inside_kernel (in))           /* User space */
677             error_code |= 4;
678           klog (LOG_INFO, "%s[%d]: segfault at %08x rip %08x rsp %08x error %d",
679                           __progname, myself->pid,
680                           e->ExceptionInformation[1], in->Eip, in->Esp,
681                           ((in->Eip >= 0x61000000 && in->Eip < 0x61200000)
682                            ? 0 : 4) | (e->ExceptionInformation[0] << 1));
683         }
684
685       /* Flag signal + core dump */
686       me.signal_exit ((cygheap->rlim_core > 0UL ? 0x80 : 0) | si.si_signo);
687     }
688
689   si.si_addr =  (si.si_signo == SIGSEGV || si.si_signo == SIGBUS
690                  ? (void *) e->ExceptionInformation[1]
691                  : (void *) in->Eip);
692   si.si_errno = si.si_pid = si.si_uid = 0;
693   me.incyg++;
694   sig_send (NULL, si, &me);     // Signal myself
695   me.incyg--;
696   e->ExceptionFlags = 0;
697   return 0;
698 }
699
700 /* Utilities to call a user supplied exception handler.  */
701
702 #define SIG_NONMASKABLE (SIGTOMASK (SIGKILL) | SIGTOMASK (SIGSTOP))
703
704 /* Non-raceable sigsuspend
705  * Note: This implementation is based on the Single UNIX Specification
706  * man page.  This indicates that sigsuspend always returns -1 and that
707  * attempts to block unblockable signals will be silently ignored.
708  * This is counter to what appears to be documented in some UNIX
709  * man pages, e.g. Linux.
710  */
711 int __stdcall
712 handle_sigsuspend (sigset_t tempmask)
713 {
714   sigset_t oldmask = _my_tls.sigmask;   // Remember for restoration
715
716   set_signal_mask (tempmask, _my_tls.sigmask);
717   sigproc_printf ("oldmask %p, newmask %p", oldmask, tempmask);
718
719   pthread_testcancel ();
720   cancelable_wait (signal_arrived);
721
722   set_sig_errno (EINTR);        // Per POSIX
723
724   /* A signal dispatch function will have been added to our stack and will
725      be hit eventually.  Set the old mask to be restored when the signal
726      handler returns and indicate its presence by modifying deltamask. */
727
728   _my_tls.deltamask |= SIG_NONMASKABLE;
729   _my_tls.oldmask = oldmask;    // Will be restored by signal handler
730   return -1;
731 }
732
733 extern DWORD exec_exit;         // Possible exit value for exec
734
735 extern "C" {
736 static void
737 sig_handle_tty_stop (int sig)
738 {
739   _my_tls.incyg = 1;
740   /* Silently ignore attempts to suspend if there is no accommodating
741      cygwin parent to deal with this behavior. */
742   if (!myself->cygstarted)
743     {
744       myself->process_state &= ~PID_STOPPED;
745       return;
746     }
747
748   myself->stopsig = sig;
749   myself->alert_parent (sig);
750   sigproc_printf ("process %d stopped by signal %d", myself->pid, sig);
751   HANDLE w4[2];
752   w4[0] = sigCONT;
753   w4[1] = signal_arrived;
754   switch (WaitForMultipleObjects (2, w4, TRUE, INFINITE))
755     {
756     case WAIT_OBJECT_0:
757     case WAIT_OBJECT_0 + 1:
758       reset_signal_arrived ();
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   // sigproc_printf ("errno %d", e);
833 }
834
835 static int setup_handler (int, void *, struct sigaction&, _cygtls *tls)
836   __attribute__((regparm(3)));
837 static int
838 setup_handler (int sig, void *handler, struct sigaction& siga, _cygtls *tls)
839 {
840   CONTEXT cx;
841   bool interrupted = false;
842
843   if (tls->sig)
844     {
845       sigproc_printf ("trying to send signal %d but signal %d already armed",
846                       sig, tls->sig);
847       goto out;
848     }
849
850   for (int n = 0; n < CALL_HANDLER_RETRY_OUTER; n++)
851     {
852       for (int i = 0; i < CALL_HANDLER_RETRY_INNER; i++)
853         {
854           tls->lock ();
855           if (tls->incyg)
856             {
857               sigproc_printf ("controlled interrupt. stackptr %p, stack %p, stackptr[-1] %p",
858                               tls->stackptr, tls->stack, tls->stackptr[-1]);
859               tls->interrupt_setup (sig, handler, siga);
860               interrupted = true;
861               tls->unlock ();
862               goto out;
863             }
864
865           DWORD res;
866           HANDLE hth = (HANDLE) *tls;
867
868           /* Suspend the thread which will receive the signal.
869              If one of these conditions is not true we loop.
870              If the thread is already suspended (which can occur when a program
871              has called SuspendThread on itself) then just queue the signal. */
872
873           sigproc_printf ("suspending thread");
874           res = SuspendThread (hth);
875           /* Just set pending if thread is already suspended */
876           if (res)
877             {
878               ResumeThread (hth);
879               goto out;
880             }
881           cx.ContextFlags = CONTEXT_CONTROL | CONTEXT_INTEGER;
882           if (!GetThreadContext (hth, &cx))
883             system_printf ("couldn't get context of thread, %E");
884           else
885             interrupted = tls->interrupt_now (&cx, sig, handler, siga);
886
887           tls->unlock ();
888           res = ResumeThread (hth);
889           if (interrupted)
890             goto out;
891
892           sigproc_printf ("couldn't interrupt.  trying again.");
893           yield ();
894         }
895       /* Hit here if we couldn't deliver the signal.  Take a more drastic
896          action before trying again. */
897       Sleep (1);
898     }
899
900 out:
901   sigproc_printf ("signal %d %sdelivered", sig, interrupted ? "" : "not ");
902   return interrupted;
903 }
904
905 static inline bool
906 has_visible_window_station ()
907 {
908   HWINSTA station_hdl;
909   USEROBJECTFLAGS uof;
910   DWORD len;
911
912   /* Check if the process is associated with a visible window station.
913      These are processes running on the local desktop as well as processes
914      running in terminal server sessions.
915      Processes running in a service session not explicitely associated
916      with the desktop (using the "Allow service to interact with desktop"
917      property) are running in an invisible window station. */
918   if ((station_hdl = GetProcessWindowStation ())
919       && GetUserObjectInformationW (station_hdl, UOI_FLAGS, &uof,
920                                     sizeof uof, &len)
921       && (uof.dwFlags & WSF_VISIBLE))
922     return true;
923   return false;
924 }
925
926 /* Keyboard interrupt handler.  */
927 static BOOL WINAPI
928 ctrl_c_handler (DWORD type)
929 {
930   static bool saw_close;
931   lock_process now;
932
933   if (!cygwin_finished_initializing)
934     {
935       if (myself->cygstarted)   /* Was this process created by a cygwin process? */
936         return TRUE;            /* Yes.  Let the parent eventually handle CTRL-C issues. */
937       debug_printf ("exiting with status %p", STATUS_CONTROL_C_EXIT);
938       ExitProcess (STATUS_CONTROL_C_EXIT);
939     }
940
941   _my_tls.remove (INFINITE);
942
943 #if 0
944   if (type == CTRL_C_EVENT || type == CTRL_BREAK_EVENT)
945     proc_subproc (PROC_KILLFORKED, 0);
946 #endif
947
948   /* Return FALSE to prevent an "End task" dialog box from appearing
949      for each Cygwin process window that's open when the computer
950      is shut down or console window is closed. */
951
952   if (type == CTRL_SHUTDOWN_EVENT)
953     {
954 #if 0
955       /* Don't send a signal.  Only NT service applications and their child
956          processes will receive this event and the services typically already
957          handle the shutdown action when getting the SERVICE_CONTROL_SHUTDOWN
958          control message. */
959       sig_send (NULL, SIGTERM);
960 #endif
961       return FALSE;
962     }
963
964   if (myself->ctty != -1)
965     {
966       if (type == CTRL_CLOSE_EVENT)
967         {
968           sig_send (NULL, SIGHUP);
969           saw_close = true;
970           return FALSE;
971         }
972       if (!saw_close && type == CTRL_LOGOFF_EVENT)
973         {
974           /* The CTRL_LOGOFF_EVENT is sent when *any* user logs off.
975              The below code sends a SIGHUP only if it is not performing the
976              default activity for SIGHUP.  Note that it is possible for two
977              SIGHUP signals to arrive if a process group leader is exiting
978              too.  Getting this 100% right is saved for a future cygwin mailing
979              list goad.  */
980           if (global_sigs[SIGHUP].sa_handler != SIG_DFL)
981             {
982               sig_send (myself_nowait, SIGHUP);
983               return TRUE;
984             }
985           return FALSE;
986         }
987     }
988
989   if (ch_spawn.set_saw_ctrl_c ())
990     return TRUE;
991
992   /* We're only the process group leader when we have a valid pinfo structure.
993      If we don't have one, then the parent "stub" will handle the signal. */
994   if (!pinfo (cygwin_pid (GetCurrentProcessId ())))
995     return TRUE;
996
997   tty_min *t = cygwin_shared->tty.get_cttyp ();
998   /* Ignore this if we're not the process group leader since it should be handled
999      *by* the process group leader. */
1000   if (t && t->getpgid () == myself->pid &&
1001        (GetTickCount () - t->last_ctrl_c) >= MIN_CTRL_C_SLOP)
1002     /* Otherwise we just send a SIGINT to the process group and return TRUE (to indicate
1003        that we have handled the signal).  At this point, type should be
1004        a CTRL_C_EVENT or CTRL_BREAK_EVENT. */
1005     {
1006       int sig = SIGINT;
1007       /* If intr and quit are both mapped to ^C, send SIGQUIT on ^BREAK */
1008       if (type == CTRL_BREAK_EVENT
1009           && t->ti.c_cc[VINTR] == 3 && t->ti.c_cc[VQUIT] == 3)
1010         sig = SIGQUIT;
1011       t->last_ctrl_c = GetTickCount ();
1012       killsys (-myself->pid, sig);
1013       t->last_ctrl_c = GetTickCount ();
1014       return TRUE;
1015     }
1016
1017   return TRUE;
1018 }
1019
1020 /* Function used by low level sig wrappers. */
1021 extern "C" void __stdcall
1022 set_process_mask (sigset_t newmask)
1023 {
1024   set_signal_mask (newmask, _my_tls.sigmask);
1025 }
1026
1027 extern "C" int
1028 sighold (int sig)
1029 {
1030   /* check that sig is in right range */
1031   if (sig < 0 || sig >= NSIG)
1032     {
1033       set_errno (EINVAL);
1034       syscall_printf ("signal %d out of range", sig);
1035       return -1;
1036     }
1037   mask_sync.acquire (INFINITE);
1038   sigset_t mask = _my_tls.sigmask;
1039   sigaddset (&mask, sig);
1040   set_signal_mask (mask, _my_tls.sigmask);
1041   mask_sync.release ();
1042   return 0;
1043 }
1044
1045 extern "C" int
1046 sigrelse (int sig)
1047 {
1048   /* check that sig is in right range */
1049   if (sig < 0 || sig >= NSIG)
1050     {
1051       set_errno (EINVAL);
1052       syscall_printf ("signal %d out of range", sig);
1053       return -1;
1054     }
1055   mask_sync.acquire (INFINITE);
1056   sigset_t mask = _my_tls.sigmask;
1057   sigdelset (&mask, sig);
1058   set_signal_mask (mask, _my_tls.sigmask);
1059   mask_sync.release ();
1060   return 0;
1061 }
1062
1063 extern "C" _sig_func_ptr
1064 sigset (int sig, _sig_func_ptr func)
1065 {
1066   sig_dispatch_pending ();
1067   _sig_func_ptr prev;
1068
1069   /* check that sig is in right range */
1070   if (sig < 0 || sig >= NSIG || sig == SIGKILL || sig == SIGSTOP)
1071     {
1072       set_errno (EINVAL);
1073       syscall_printf ("SIG_ERR = sigset (%d, %p)", sig, func);
1074       return (_sig_func_ptr) SIG_ERR;
1075     }
1076
1077   mask_sync.acquire (INFINITE);
1078   sigset_t mask = _my_tls.sigmask;
1079   /* If sig was in the signal mask return SIG_HOLD, otherwise return the
1080      previous disposition. */
1081   if (sigismember (&mask, sig))
1082     prev = SIG_HOLD;
1083   else
1084     prev = global_sigs[sig].sa_handler;
1085   /* If func is SIG_HOLD, add sig to the signal mask, otherwise set the
1086      disposition to func and remove sig from the signal mask. */
1087   if (func == SIG_HOLD)
1088     sigaddset (&mask, sig);
1089   else
1090     {
1091       /* No error checking.  The test which could return SIG_ERR has already
1092          been made above. */
1093       signal (sig, func);
1094       sigdelset (&mask, sig);
1095     }
1096   set_signal_mask (mask, _my_tls.sigmask);
1097   mask_sync.release ();
1098   return prev;
1099 }
1100
1101 extern "C" int
1102 sigignore (int sig)
1103 {
1104   return sigset (sig, SIG_IGN) == SIG_ERR ? -1 : 0;
1105 }
1106
1107 /* Update the signal mask for this process and return the old mask.
1108    Called from sigdelayed */
1109 extern "C" sigset_t
1110 set_process_mask_delta ()
1111 {
1112   mask_sync.acquire (INFINITE);
1113   sigset_t newmask, oldmask;
1114
1115   if (_my_tls.deltamask & SIG_NONMASKABLE)
1116     oldmask = _my_tls.oldmask; /* from handle_sigsuspend */
1117   else
1118     oldmask = _my_tls.sigmask;
1119   newmask = (oldmask | _my_tls.deltamask) & ~SIG_NONMASKABLE;
1120   sigproc_printf ("oldmask %p, newmask %p, deltamask %p", oldmask, newmask,
1121                   _my_tls.deltamask);
1122   _my_tls.sigmask = newmask;
1123   mask_sync.release ();
1124   return oldmask;
1125 }
1126
1127 /* Set the signal mask for this process.
1128    Note that some signals are unmaskable, as in UNIX.  */
1129 extern "C" void __stdcall
1130 set_signal_mask (sigset_t newmask, sigset_t& oldmask)
1131 {
1132 #ifdef CGF
1133   if (&_my_tls == _sig_tls)
1134     small_printf ("********* waiting in signal thread\n");
1135 #endif
1136   mask_sync.acquire (INFINITE);
1137   newmask &= ~SIG_NONMASKABLE;
1138   sigset_t mask_bits = oldmask & ~newmask;
1139   sigproc_printf ("oldmask %p, newmask %p, mask_bits %p", oldmask, newmask,
1140                   mask_bits);
1141   oldmask = newmask;
1142   if (mask_bits)
1143     sig_dispatch_pending (true);
1144   else
1145     sigproc_printf ("not calling sig_dispatch_pending");
1146   mask_sync.release ();
1147 }
1148
1149 int __stdcall
1150 sigpacket::process ()
1151 {
1152   DWORD continue_now;
1153   struct sigaction dummy = global_sigs[SIGSTOP];
1154
1155   if (si.si_signo != SIGCONT)
1156     continue_now = false;
1157   else
1158     {
1159       continue_now = myself->process_state & PID_STOPPED;
1160       myself->stopsig = 0;
1161       myself->process_state &= ~PID_STOPPED;
1162       /* Clear pending stop signals */
1163       sig_clear (SIGSTOP);
1164       sig_clear (SIGTSTP);
1165       sig_clear (SIGTTIN);
1166       sig_clear (SIGTTOU);
1167     }
1168
1169   switch (si.si_signo)
1170     {
1171     case SIGINT:
1172     case SIGQUIT:
1173     case SIGSTOP:
1174     case SIGTSTP:
1175       if (cygheap->ctty)
1176         cygheap->ctty->sigflush ();
1177       break;
1178     default:
1179       break;
1180     }
1181
1182   int rc = 1;
1183
1184   sigproc_printf ("signal %d processing", si.si_signo);
1185   struct sigaction& thissig = global_sigs[si.si_signo];
1186
1187   myself->rusage_self.ru_nsignals++;
1188
1189   bool masked;
1190   void *handler;
1191   if (!have_execed || (void *) thissig.sa_handler == (void *) SIG_IGN)
1192     handler = (void *) thissig.sa_handler;
1193   else if (tls)
1194     return 1;
1195   else
1196     handler = NULL;
1197
1198   _cygtls *use_tls = tls ?: _main_tls;
1199
1200   if (si.si_signo == SIGKILL)
1201     goto exit_sig;
1202   if (si.si_signo == SIGSTOP)
1203     {
1204       sig_clear (SIGCONT);
1205       goto stop;
1206     }
1207
1208   bool insigwait_mask;
1209   if ((masked = ISSTATE (myself, PID_STOPPED)))
1210     insigwait_mask = false;
1211   else if (tls)
1212     insigwait_mask = sigismember (&tls->sigwait_mask, si.si_signo);
1213   else if (!(tls = _cygtls::find_tls (si.si_signo)))
1214     insigwait_mask = false;
1215   else
1216     {
1217       use_tls = tls;
1218       insigwait_mask = true;
1219     }
1220
1221   if (insigwait_mask)
1222     goto thread_specific;
1223
1224   if (masked)
1225     /* nothing to do */;
1226   else if (sigismember (mask, si.si_signo))
1227     masked = true;
1228   else if (tls)
1229     masked  = sigismember (&tls->sigmask, si.si_signo);
1230
1231   if (masked)
1232     {
1233       sigproc_printf ("signal %d blocked", si.si_signo);
1234       rc = -1;
1235       goto done;
1236     }
1237
1238   /* Clear pending SIGCONT on stop signals */
1239   if (si.si_signo == SIGTSTP || si.si_signo == SIGTTIN || si.si_signo == SIGTTOU)
1240     sig_clear (SIGCONT);
1241
1242 #ifdef CGF
1243   if (being_debugged ())
1244     {
1245       char sigmsg[sizeof (_CYGWIN_SIGNAL_STRING " 0xffffffff")];
1246       __small_sprintf (sigmsg, _CYGWIN_SIGNAL_STRING " %p", si.si_signo);
1247       OutputDebugString (sigmsg);
1248     }
1249 #endif
1250
1251   if (handler == (void *) SIG_DFL)
1252     {
1253       if (insigwait_mask)
1254         goto thread_specific;
1255       if (si.si_signo == SIGCHLD || si.si_signo == SIGIO || si.si_signo == SIGCONT || si.si_signo == SIGWINCH
1256           || si.si_signo == SIGURG)
1257         {
1258           sigproc_printf ("default signal %d ignored", si.si_signo);
1259           if (continue_now)
1260             SetEvent (signal_arrived);
1261           goto done;
1262         }
1263
1264       if (si.si_signo == SIGTSTP || si.si_signo == SIGTTIN || si.si_signo == SIGTTOU)
1265         goto stop;
1266
1267       goto exit_sig;
1268     }
1269
1270   if (handler == (void *) SIG_IGN)
1271     {
1272       sigproc_printf ("signal %d ignored", si.si_signo);
1273       goto done;
1274     }
1275
1276   if (handler == (void *) SIG_ERR)
1277     goto exit_sig;
1278
1279   use_tls->set_siginfo (this);
1280   goto dosig;
1281
1282 stop:
1283   /* Eat multiple attempts to STOP */
1284   if (ISSTATE (myself, PID_STOPPED))
1285     goto done;
1286   handler = (void *) sig_handle_tty_stop;
1287   thissig = dummy;
1288
1289 dosig:
1290   /* Dispatch to the appropriate function. */
1291   sigproc_printf ("signal %d, about to call %p", si.si_signo, handler);
1292   rc = setup_handler (si.si_signo, handler, thissig, use_tls);
1293
1294 done:
1295   tls = use_tls;
1296   if (continue_now)
1297     SetEvent (sigCONT);
1298   sigproc_printf ("returning %d", rc);
1299   return rc;
1300
1301 thread_specific:
1302   use_tls->sig = si.si_signo;
1303   use_tls->set_siginfo (this);
1304   use_tls->func = NULL;
1305   sigproc_printf ("releasing sigwait for thread");
1306   SetEvent (use_tls->event);
1307   goto done;
1308
1309 exit_sig:
1310   use_tls->signal_exit (si.si_signo);   /* never returns */
1311 }
1312
1313 void
1314 events_init ()
1315 {
1316   mask_sync.init ("mask_sync");
1317 }
1318
1319 void
1320 events_terminate ()
1321 {
1322   exit_already = 1;
1323 }
1324
1325 int
1326 _cygtls::call_signal_handler ()
1327 {
1328   int this_sa_flags = 0;
1329   /* Call signal handler.  */
1330   while (sig && func)
1331     {
1332       lock ();
1333       this_sa_flags = sa_flags;
1334       int thissig = sig;
1335       void (*thisfunc) (int) = func;
1336
1337       pop ();
1338       reset_signal_arrived ();
1339       sigset_t this_oldmask = set_process_mask_delta ();
1340       int this_errno = saved_errno;
1341       sig = 0;
1342       unlock ();        // make sure synchronized
1343       incyg = 0;
1344       if (!(this_sa_flags & SA_SIGINFO))
1345         {
1346           void (*sigfunc) (int) = thisfunc;
1347           sigfunc (thissig);
1348         }
1349       else
1350         {
1351           siginfo_t thissi = infodata;
1352           void (*sigact) (int, siginfo_t *, void *) = (void (*) (int, siginfo_t *, void *)) thisfunc;
1353           /* no ucontext_t information provided yet */
1354           sigact (thissig, &thissi, NULL);
1355         }
1356       incyg = 1;
1357       set_signal_mask (this_oldmask, _my_tls.sigmask);
1358       if (this_errno >= 0)
1359         set_errno (this_errno);
1360     }
1361
1362   return this_sa_flags & SA_RESTART;
1363 }
1364
1365 extern "C" void __stdcall
1366 reset_signal_arrived ()
1367 {
1368   // NEEDED? WaitForSingleObject (signal_arrived, 10);
1369   ResetEvent (signal_arrived);
1370   sigproc_printf ("reset signal_arrived");
1371   if (_my_tls.stackptr > _my_tls.stack)
1372     debug_printf ("stackptr[-1] %p", _my_tls.stackptr[-1]);
1373 }
1374
1375 void
1376 _cygtls::copy_context (CONTEXT *c)
1377 {
1378   memcpy (&thread_context, c, (&thread_context._internal - (unsigned char *) &thread_context));
1379 }
1380
1381 void
1382 _cygtls::signal_debugger (int sig)
1383 {
1384   if (isinitialized () && being_debugged ())
1385     {
1386       char sigmsg[2 * sizeof (_CYGWIN_SIGNAL_STRING " ffffffff ffffffff")];
1387       __small_sprintf (sigmsg, _CYGWIN_SIGNAL_STRING " %d %p %p", sig, thread_id, &thread_context);
1388       OutputDebugString (sigmsg);
1389     }
1390 }