OSDN Git Service

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