OSDN Git Service

Remove extraneous whitespace.
[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 ((void *)e->ExceptionInformation[1],
530                                              1))
531         {
532         case MMAP_NORESERVE_COMMITED:
533           return 0;
534         case MMAP_RAISE_SIGBUS: /* MAP_NORESERVE page, commit failed, or
535                                    access to mmap page beyond EOF. */
536           si.si_signo = SIGBUS;
537           si.si_code = BUS_OBJERR;
538           break;
539         default:
540           MEMORY_BASIC_INFORMATION m;
541           VirtualQuery ((PVOID) e->ExceptionInformation[1], &m, sizeof m);
542           si.si_signo = SIGSEGV;
543           si.si_code = m.State == MEM_FREE ? SEGV_MAPERR : SEGV_ACCERR;
544           break;
545         }
546       break;
547
548     case STATUS_ARRAY_BOUNDS_EXCEEDED:
549     case STATUS_IN_PAGE_ERROR:
550     case STATUS_NO_MEMORY:
551     case STATUS_INVALID_DISPOSITION:
552     case STATUS_STACK_OVERFLOW:
553       si.si_signo = SIGSEGV;
554       si.si_code = SEGV_MAPERR;
555       break;
556
557     case STATUS_CONTROL_C_EXIT:
558       si.si_signo = SIGINT;
559       break;
560
561     case STATUS_INVALID_HANDLE:
562       /* CloseHandle will throw this exception if it is given an
563          invalid handle.  We don't care about the exception; we just
564          want CloseHandle to return an error.  This can be revisited
565          if gcc ever supports Windows style structured exception
566          handling.  */
567       return 0;
568
569     default:
570       /* If we don't recognize the exception, we have to assume that
571          we are doing structured exception handling, and we let
572          something else handle it.  */
573       return 1;
574     }
575
576   rtl_unwind (frame, e);
577
578   debug_printf ("In cygwin_except_handler exc %p at %p sp %p", e->ExceptionCode, in->Eip, in->Esp);
579   debug_printf ("In cygwin_except_handler sig %d at %p", si.si_signo, in->Eip);
580
581   if (global_sigs[si.si_signo].sa_mask & SIGTOMASK (si.si_signo))
582     syscall_printf ("signal %d, masked %p", si.si_signo,
583                     global_sigs[si.si_signo].sa_mask);
584
585   debug_printf ("In cygwin_except_handler calling %p",
586                  global_sigs[si.si_signo].sa_handler);
587
588   DWORD *ebp = (DWORD *) in->Esp;
589   for (DWORD *bpend = (DWORD *) __builtin_frame_address (0); ebp > bpend; ebp--)
590     if (*ebp == in->SegCs && ebp[-1] == in->Eip)
591       {
592         ebp -= 2;
593         break;
594       }
595
596   if (me.fault_guarded ())
597     me.return_from_fault ();
598
599   me.copy_context (in);
600   if (!cygwin_finished_initializing
601       || &me == _sig_tls
602       || (void *) global_sigs[si.si_signo].sa_handler == (void *) SIG_DFL
603       || (void *) global_sigs[si.si_signo].sa_handler == (void *) SIG_IGN
604       || (void *) global_sigs[si.si_signo].sa_handler == (void *) SIG_ERR)
605     {
606       /* Print the exception to the console */
607       if (!myself->cygstarted)
608         for (int i = 0; status_info[i].name; i++)
609           if (status_info[i].code == e->ExceptionCode)
610             {
611               system_printf ("Exception: %s", status_info[i].name);
612               break;
613             }
614
615       /* Another exception could happen while tracing or while exiting.
616          Only do this once.  */
617       if (recursed++)
618         system_printf ("Error while dumping state (probably corrupted stack)");
619       else
620         {
621           if (try_to_debug (0))
622             {
623               debugging = true;
624               return 0;
625             }
626
627           open_stackdumpfile ();
628           exception (e, in);
629           stackdump ((DWORD) ebp, 0, 1);
630         }
631
632       if (e->ExceptionCode == STATUS_ACCESS_VIOLATION)
633         {
634           int error_code = 0;
635           if (si.si_code == SEGV_ACCERR)        /* Address present */
636             error_code |= 1;
637           if (e->ExceptionInformation[0])       /* Write access */
638             error_code |= 2;
639           if (!inside_kernel (in))              /* User space */
640             error_code |= 4;
641           klog (LOG_INFO, "%s[%d]: segfault at %08x rip %08x rsp %08x error %d",
642                           __progname, myself->pid,
643                           e->ExceptionInformation[1], in->Eip, in->Esp,
644                           ((in->Eip >= 0x61000000 && in->Eip < 0x61200000)
645                            ? 0 : 4) | (e->ExceptionInformation[0] << 1));
646         }
647
648       me.signal_exit (0x80 | si.si_signo);      // Flag signal + core dump
649     }
650
651   si.si_addr = (void *) in->Eip;
652   si.si_errno = si.si_pid = si.si_uid = 0;
653   me.incyg++;
654   sig_send (NULL, si, &me);     // Signal myself
655   me.incyg--;
656   e->ExceptionFlags = 0;
657   return 0;
658 }
659
660 /* Utilities to call a user supplied exception handler.  */
661
662 #define SIG_NONMASKABLE (SIGTOMASK (SIGKILL) | SIGTOMASK (SIGSTOP))
663
664 /* Non-raceable sigsuspend
665  * Note: This implementation is based on the Single UNIX Specification
666  * man page.  This indicates that sigsuspend always returns -1 and that
667  * attempts to block unblockable signals will be silently ignored.
668  * This is counter to what appears to be documented in some UNIX
669  * man pages, e.g. Linux.
670  */
671 int __stdcall
672 handle_sigsuspend (sigset_t tempmask)
673 {
674   if (&_my_tls != _main_tls)
675     {
676       cancelable_wait (signal_arrived, INFINITE, cw_cancel_self);
677       return -1;
678     }
679
680   sigset_t oldmask = myself->getsigmask ();     // Remember for restoration
681
682   set_signal_mask (tempmask, myself->getsigmask ());
683   sigproc_printf ("oldmask %p, newmask %p", oldmask, tempmask);
684
685   pthread_testcancel ();
686   cancelable_wait (signal_arrived, INFINITE);
687
688   set_sig_errno (EINTR);        // Per POSIX
689
690   /* A signal dispatch function will have been added to our stack and will
691      be hit eventually.  Set the old mask to be restored when the signal
692      handler returns and indicate its presence by modifying deltamask. */
693
694   _my_tls.deltamask |= SIG_NONMASKABLE;
695   _my_tls.oldmask = oldmask;    // Will be restored by signal handler
696   return -1;
697 }
698
699 extern DWORD exec_exit;         // Possible exit value for exec
700
701 extern "C" {
702 static void
703 sig_handle_tty_stop (int sig)
704 {
705   _my_tls.incyg = 1;
706   /* Silently ignore attempts to suspend if there is no accommodating
707      cygwin parent to deal with this behavior. */
708   if (!myself->cygstarted)
709     {
710       myself->process_state &= ~PID_STOPPED;
711       return;
712     }
713
714   myself->stopsig = sig;
715   myself->alert_parent (sig);
716   sigproc_printf ("process %d stopped by signal %d", myself->pid, sig);
717   HANDLE w4[2];
718   w4[0] = sigCONT;
719   w4[1] = signal_arrived;
720   switch (WaitForMultipleObjects (2, w4, TRUE, INFINITE))
721     {
722     case WAIT_OBJECT_0:
723     case WAIT_OBJECT_0 + 1:
724       reset_signal_arrived ();
725       myself->alert_parent (SIGCONT);
726       break;
727     default:
728       api_fatal ("WaitSingleObject failed, %E");
729       break;
730     }
731   _my_tls.incyg = 0;
732 }
733 }
734
735 bool
736 _cygtls::interrupt_now (CONTEXT *cx, int sig, void *handler,
737                         struct sigaction& siga)
738 {
739   bool interrupted;
740
741   if (incyg || spinning || locked () || inside_kernel (cx))
742     interrupted = false;
743   else
744     {
745       push ((__stack_t) cx->Eip);
746       interrupt_setup (sig, handler, siga);
747       cx->Eip = pop ();
748       SetThreadContext (*this, cx); /* Restart the thread in a new location */
749       interrupted = true;
750     }
751   return interrupted;
752 }
753
754 void __stdcall
755 _cygtls::interrupt_setup (int sig, void *handler, struct sigaction& siga)
756 {
757   push ((__stack_t) sigdelayed);
758   deltamask = siga.sa_mask & ~SIG_NONMASKABLE;
759   sa_flags = siga.sa_flags;
760   func = (void (*) (int)) handler;
761   if (siga.sa_flags & SA_RESETHAND)
762     siga.sa_handler = SIG_DFL;
763   saved_errno = -1;             // Flag: no errno to save
764   if (handler == sig_handle_tty_stop)
765     {
766       myself->stopsig = 0;
767       myself->process_state |= PID_STOPPED;
768     }
769
770   this->sig = sig;                      // Should always be last thing set to avoid a race
771
772   if (!event)
773     threadkill = false;
774   else
775     {
776       HANDLE h = event;
777       event = NULL;
778       SetEvent (h);
779     }
780
781   /* Clear any waiting threads prior to dispatching to handler function */
782   int res = SetEvent (signal_arrived);  // For an EINTR case
783   proc_subproc (PROC_CLEARWAIT, 1);
784   sigproc_printf ("armed signal_arrived %p, sig %d, res %d", signal_arrived,
785                   sig, res);
786 }
787
788 extern "C" void __stdcall
789 set_sig_errno (int e)
790 {
791   *_my_tls.errno_addr = e;
792   _my_tls.saved_errno = e;
793   // sigproc_printf ("errno %d", e);
794 }
795
796 static int setup_handler (int, void *, struct sigaction&, _cygtls *tls)
797   __attribute__((regparm(3)));
798 static int
799 setup_handler (int sig, void *handler, struct sigaction& siga, _cygtls *tls)
800 {
801   CONTEXT cx;
802   bool interrupted = false;
803
804   if (tls->sig)
805     {
806       sigproc_printf ("trying to send sig %d but signal %d already armed",
807                       sig, tls->sig);
808       goto out;
809     }
810
811   for (int i = 0; i < CALL_HANDLER_RETRY; i++)
812     {
813       tls->lock ();
814       if (tls->incyg)
815         {
816           sigproc_printf ("controlled interrupt. stackptr %p, stack %p, stackptr[-1] %p",
817                           tls->stackptr, tls->stack, tls->stackptr[-1]);
818           tls->interrupt_setup (sig, handler, siga);
819           interrupted = true;
820           tls->unlock ();
821           break;
822         }
823
824       tls->unlock ();
825       DWORD res;
826       HANDLE hth = (HANDLE) *tls;
827
828       /* Suspend the thread which will receive the signal.
829          For Windows 95, we also have to ensure that the addresses returned by
830          GetThreadContext are valid.
831          If one of these conditions is not true we loop for a fixed number of times
832          since we don't want to stall the signal handler.  FIXME: Will this result in
833          noticeable delays?
834          If the thread is already suspended (which can occur when a program has called
835          SuspendThread on itself) then just queue the signal. */
836
837 #ifndef DEBUGGING
838       sigproc_printf ("suspending mainthread");
839 #else
840       cx.ContextFlags = CONTEXT_CONTROL | CONTEXT_INTEGER;
841       if (!GetThreadContext (hth, &cx))
842         memset (&cx, 0, sizeof cx);
843       sigproc_printf ("suspending mainthread PC %p", cx.Eip);
844 #endif
845       res = SuspendThread (hth);
846       /* Just set pending if thread is already suspended */
847       if (res)
848         {
849           ResumeThread (hth);
850           break;
851         }
852       cx.ContextFlags = CONTEXT_CONTROL | CONTEXT_INTEGER;
853       if (!GetThreadContext (hth, &cx))
854         system_printf ("couldn't get context of main thread, %E");
855       else
856         interrupted = tls->interrupt_now (&cx, sig, handler, siga);
857
858       res = ResumeThread (hth);
859       if (interrupted)
860         break;
861
862       sigproc_printf ("couldn't interrupt.  trying again.");
863       low_priority_sleep (0);
864     }
865
866 out:
867   sigproc_printf ("signal %d %sdelivered", sig, interrupted ? "" : "not ");
868   return interrupted;
869 }
870
871 static inline bool
872 has_visible_window_station ()
873 {
874   HWINSTA station_hdl;
875   USEROBJECTFLAGS uof;
876   DWORD len;
877
878   /* Check if the process is associated with a visible window station.
879      These are processes running on the local desktop as well as processes
880      running in terminal server sessions.
881      Processes running in a service session not explicitely associated
882      with the desktop (using the "Allow service to interact with desktop"
883      property) are running in an invisible window station. */
884   if ((station_hdl = GetProcessWindowStation ())
885       && GetUserObjectInformationA (station_hdl, UOI_FLAGS, &uof,
886                                     sizeof uof, &len)
887       && (uof.dwFlags & WSF_VISIBLE))
888     return true;
889   return false;
890 }
891
892 /* Keyboard interrupt handler.  */
893 static BOOL WINAPI
894 ctrl_c_handler (DWORD type)
895 {
896   static bool saw_close;
897
898   if (!cygwin_finished_initializing)
899     {
900       if (myself->cygstarted)   /* Was this process created by a cygwin process? */
901         return TRUE;            /* Yes.  Let the parent eventually handle CTRL-C issues. */
902       debug_printf ("exiting with status %p", STATUS_CONTROL_C_EXIT);
903       ExitProcess (STATUS_CONTROL_C_EXIT);
904     }
905
906   _my_tls.remove (INFINITE);
907
908 #if 0
909   if (type == CTRL_C_EVENT || type == CTRL_BREAK_EVENT)
910     proc_subproc (PROC_KILLFORKED, 0);
911 #endif
912
913   /* Return FALSE to prevent an "End task" dialog box from appearing
914      for each Cygwin process window that's open when the computer
915      is shut down or console window is closed. */
916
917   if (type == CTRL_SHUTDOWN_EVENT)
918     {
919 #if 0
920       /* Don't send a signal.  Only NT service applications and their child
921          processes will receive this event and the services typically already
922          handle the shutdown action when getting the SERVICE_CONTROL_SHUTDOWN
923          control message. */
924       sig_send (NULL, SIGTERM);
925 #endif
926       return FALSE;
927     }
928
929   if (myself->ctty != -1)
930     {
931       if (type == CTRL_CLOSE_EVENT)
932         {
933           sig_send (NULL, SIGHUP);
934           saw_close = true;
935           return FALSE;
936         }
937       if (!saw_close && type == CTRL_LOGOFF_EVENT)
938         {
939           /* The CTRL_LOGOFF_EVENT is sent when *any* user logs off.
940              The below code sends a SIGHUP only if it is not performing the
941              default activity for SIGHUP.  Note that it is possible for two
942              SIGHUP signals to arrive if a process group leader is exiting
943              too.  Getting this 100% right is saved for a future cygwin mailing
944              list goad.  */
945           if (global_sigs[SIGHUP].sa_handler != SIG_DFL)
946             {
947               sig_send (myself_nowait, SIGHUP);
948               return TRUE;
949             }
950           return FALSE;
951         }
952     }
953
954   if (chExeced)
955     {
956       chExeced->set_saw_ctrl_c ();
957       return TRUE;
958     }
959
960   /* We're only the process group leader when we have a valid pinfo structure.
961      If we don't have one, then the parent "stub" will handle the signal. */
962   if (!pinfo (cygwin_pid (GetCurrentProcessId ())))
963     return TRUE;
964
965   tty_min *t = cygwin_shared->tty.get_tty (myself->ctty);
966   /* Ignore this if we're not the process group leader since it should be handled
967      *by* the process group leader. */
968   if (myself->ctty != -1 && t->getpgid () == myself->pid &&
969        (GetTickCount () - t->last_ctrl_c) >= MIN_CTRL_C_SLOP)
970     /* Otherwise we just send a SIGINT to the process group and return TRUE (to indicate
971        that we have handled the signal).  At this point, type should be
972        a CTRL_C_EVENT or CTRL_BREAK_EVENT. */
973     {
974       int sig = SIGINT;
975       /* If intr and quit are both mapped to ^C, send SIGQUIT on ^BREAK */
976       if (type == CTRL_BREAK_EVENT
977           && t->ti.c_cc[VINTR] == 3 && t->ti.c_cc[VQUIT] == 3)
978         sig = SIGQUIT;
979       t->last_ctrl_c = GetTickCount ();
980       killsys (-myself->pid, sig);
981       t->last_ctrl_c = GetTickCount ();
982       return TRUE;
983     }
984
985   return TRUE;
986 }
987
988 /* Function used by low level sig wrappers. */
989 extern "C" void __stdcall
990 set_process_mask (sigset_t newmask)
991 {
992   set_signal_mask (newmask, myself->getsigmask ());
993 sigproc_printf ("mask now %p\n", myself->getsigmask ());
994 }
995
996 extern "C" int
997 sighold (int sig)
998 {
999   /* check that sig is in right range */
1000   if (sig < 0 || sig >= NSIG)
1001     {
1002       set_errno (EINVAL);
1003       syscall_printf ("signal %d out of range", sig);
1004       return -1;
1005     }
1006   mask_sync.acquire (INFINITE);
1007   sigset_t mask = myself->getsigmask ();
1008   sigaddset (&mask, sig);
1009   set_signal_mask (mask, myself->getsigmask ());
1010   mask_sync.release ();
1011   return 0;
1012 }
1013
1014 extern "C" int
1015 sigrelse (int sig)
1016 {
1017   /* check that sig is in right range */
1018   if (sig < 0 || sig >= NSIG)
1019     {
1020       set_errno (EINVAL);
1021       syscall_printf ("signal %d out of range", sig);
1022       return -1;
1023     }
1024   mask_sync.acquire (INFINITE);
1025   sigset_t mask = myself->getsigmask ();
1026   sigdelset (&mask, sig);
1027   set_signal_mask (mask, myself->getsigmask ());
1028   mask_sync.release ();
1029   return 0;
1030 }
1031
1032 extern "C" _sig_func_ptr
1033 sigset (int sig, _sig_func_ptr func)
1034 {
1035   sig_dispatch_pending ();
1036   _sig_func_ptr prev;
1037
1038   /* check that sig is in right range */
1039   if (sig < 0 || sig >= NSIG || sig == SIGKILL || sig == SIGSTOP)
1040     {
1041       set_errno (EINVAL);
1042       syscall_printf ("SIG_ERR = sigset (%d, %p)", sig, func);
1043       return (_sig_func_ptr) SIG_ERR;
1044     }
1045
1046   mask_sync.acquire (INFINITE);
1047   sigset_t mask = myself->getsigmask ();
1048   /* If sig was in the signal mask return SIG_HOLD, otherwise return the
1049      previous disposition. */
1050   if (sigismember (&mask, sig))
1051     prev = SIG_HOLD;
1052   else
1053     prev = global_sigs[sig].sa_handler;
1054   /* If func is SIG_HOLD, add sig to the signal mask, otherwise set the
1055      disposition to func and remove sig from the signal mask. */
1056   if (func == SIG_HOLD)
1057     sigaddset (&mask, sig);
1058   else
1059     {
1060       /* No error checking.  The test which could return SIG_ERR has already
1061          been made above. */
1062       signal (sig, func);
1063       sigdelset (&mask, sig);
1064     }
1065   set_signal_mask (mask, myself->getsigmask ());
1066   mask_sync.release ();
1067   return prev;
1068 }
1069
1070 extern "C" int
1071 sigignore (int sig)
1072 {
1073   return sigset (sig, SIG_IGN) == SIG_ERR ? -1 : 0;
1074 }
1075
1076 /* Update the signal mask for this process and return the old mask.
1077    Called from sigdelayed */
1078 extern "C" sigset_t
1079 set_process_mask_delta ()
1080 {
1081   mask_sync.acquire (INFINITE);
1082   sigset_t newmask, oldmask;
1083
1084   if (_my_tls.deltamask & SIG_NONMASKABLE)
1085     oldmask = _my_tls.oldmask; /* from handle_sigsuspend */
1086   else
1087     oldmask = myself->getsigmask ();
1088   newmask = (oldmask | _my_tls.deltamask) & ~SIG_NONMASKABLE;
1089   sigproc_printf ("oldmask %p, newmask %p, deltamask %p", oldmask, newmask,
1090                   _my_tls.deltamask);
1091   myself->setsigmask (newmask);
1092   mask_sync.release ();
1093   return oldmask;
1094 }
1095
1096 /* Set the signal mask for this process.
1097    Note that some signals are unmaskable, as in UNIX.  */
1098 extern "C" void __stdcall
1099 set_signal_mask (sigset_t newmask, sigset_t& oldmask)
1100 {
1101 #ifdef CGF
1102   if (&_my_tls == _sig_tls)
1103     small_printf ("********* waiting in signal thread\n");
1104 #endif
1105   mask_sync.acquire (INFINITE);
1106   newmask &= ~SIG_NONMASKABLE;
1107   sigset_t mask_bits = oldmask & ~newmask;
1108   sigproc_printf ("oldmask %p, newmask %p, mask_bits %p", oldmask, newmask,
1109                   mask_bits);
1110   oldmask = newmask;
1111   if (mask_bits)
1112     sig_dispatch_pending (true);
1113   else
1114     sigproc_printf ("not calling sig_dispatch_pending");
1115   mask_sync.release ();
1116 }
1117
1118 int __stdcall
1119 sigpacket::process ()
1120 {
1121   DWORD continue_now;
1122   struct sigaction dummy = global_sigs[SIGSTOP];
1123
1124   if (si.si_signo != SIGCONT)
1125     continue_now = false;
1126   else
1127     {
1128       continue_now = myself->process_state & PID_STOPPED;
1129       myself->stopsig = 0;
1130       myself->process_state &= ~PID_STOPPED;
1131       /* Clear pending stop signals */
1132       sig_clear (SIGSTOP);
1133       sig_clear (SIGTSTP);
1134       sig_clear (SIGTTIN);
1135       sig_clear (SIGTTOU);
1136     }
1137
1138   int rc = 1;
1139
1140   sigproc_printf ("signal %d processing", si.si_signo);
1141   struct sigaction& thissig = global_sigs[si.si_signo];
1142
1143   myself->rusage_self.ru_nsignals++;
1144
1145   bool masked;
1146   void *handler;
1147   if (!hExeced || (void *) thissig.sa_handler == (void *) SIG_IGN)
1148     handler = (void *) thissig.sa_handler;
1149   else if (tls)
1150     return 1;
1151   else
1152     handler = NULL;
1153
1154   if (si.si_signo == SIGKILL)
1155     goto exit_sig;
1156   if (si.si_signo == SIGSTOP)
1157     {
1158       sig_clear (SIGCONT);
1159       if (!tls)
1160         tls = _main_tls;
1161       goto stop;
1162     }
1163
1164   bool insigwait_mask;
1165   if ((masked = ISSTATE (myself, PID_STOPPED)))
1166     insigwait_mask = false;
1167   else if (!tls)
1168     insigwait_mask = !handler && (tls = _cygtls::find_tls (si.si_signo));
1169   else
1170     insigwait_mask = sigismember (&tls->sigwait_mask, si.si_signo);
1171
1172   if (insigwait_mask)
1173     goto thread_specific;
1174
1175   if (masked)
1176     /* nothing to do */;
1177   else if (sigismember (mask, si.si_signo))
1178     masked = true;
1179   else if (tls)
1180     masked  = sigismember (&tls->sigmask, si.si_signo);
1181
1182   if (!tls)
1183     tls = _main_tls;
1184
1185   if (masked)
1186     {
1187       sigproc_printf ("signal %d blocked", si.si_signo);
1188       rc = -1;
1189       goto done;
1190     }
1191
1192   /* Clear pending SIGCONT on stop signals */
1193   if (si.si_signo == SIGTSTP || si.si_signo == SIGTTIN || si.si_signo == SIGTTOU)
1194     sig_clear (SIGCONT);
1195
1196 #ifdef CGF
1197   if (being_debugged ())
1198     {
1199       char sigmsg[sizeof (_CYGWIN_SIGNAL_STRING " 0xffffffff")];
1200       __small_sprintf (sigmsg, _CYGWIN_SIGNAL_STRING " %p", si.si_signo);
1201       OutputDebugString (sigmsg);
1202     }
1203 #endif
1204
1205   if (handler == (void *) SIG_DFL)
1206     {
1207       if (insigwait_mask)
1208         goto thread_specific;
1209       if (si.si_signo == SIGCHLD || si.si_signo == SIGIO || si.si_signo == SIGCONT || si.si_signo == SIGWINCH
1210           || si.si_signo == SIGURG)
1211         {
1212           sigproc_printf ("default signal %d ignored", si.si_signo);
1213           if (continue_now)
1214             SetEvent (signal_arrived);
1215           goto done;
1216         }
1217
1218       if (si.si_signo == SIGTSTP || si.si_signo == SIGTTIN || si.si_signo == SIGTTOU)
1219         goto stop;
1220
1221       goto exit_sig;
1222     }
1223
1224   if (handler == (void *) SIG_IGN)
1225     {
1226       sigproc_printf ("signal %d ignored", si.si_signo);
1227       goto done;
1228     }
1229
1230   if (handler == (void *) SIG_ERR)
1231     goto exit_sig;
1232
1233   tls->set_siginfo (this);
1234   goto dosig;
1235
1236 stop:
1237   /* Eat multiple attempts to STOP */
1238   if (ISSTATE (myself, PID_STOPPED))
1239     goto done;
1240   handler = (void *) sig_handle_tty_stop;
1241   thissig = dummy;
1242
1243 dosig:
1244   /* Dispatch to the appropriate function. */
1245   sigproc_printf ("signal %d, about to call %p", si.si_signo, handler);
1246   rc = setup_handler (si.si_signo, handler, thissig, tls);
1247
1248 done:
1249   if (continue_now)
1250     SetEvent (sigCONT);
1251   sigproc_printf ("returning %d", rc);
1252   return rc;
1253
1254 thread_specific:
1255   tls->sig = si.si_signo;
1256   tls->set_siginfo (this);
1257   sigproc_printf ("releasing sigwait for thread");
1258   SetEvent (tls->event);
1259   goto done;
1260
1261 exit_sig:
1262   if (si.si_signo == SIGQUIT || si.si_signo == SIGABRT)
1263     {
1264       CONTEXT c;
1265       c.ContextFlags = CONTEXT_FULL;
1266       GetThreadContext (hMainThread, &c);
1267       tls->copy_context (&c);
1268       si.si_signo |= 0x80;
1269     }
1270   sigproc_printf ("signal %d, about to call do_exit", si.si_signo);
1271   tls->signal_exit (si.si_signo);       /* never returns */
1272 }
1273
1274 /* Cover function to `do_exit' to handle exiting even in presence of more
1275    exceptions.  We used to call exit, but a SIGSEGV shouldn't cause atexit
1276    routines to run.  */
1277 void
1278 _cygtls::signal_exit (int rc)
1279 {
1280   if (hExeced)
1281     {
1282       sigproc_printf ("terminating captive process");
1283       TerminateProcess (hExeced, sigExeced = rc);
1284     }
1285
1286   signal_debugger (rc & 0x7f);
1287   if ((rc & 0x80) && !try_to_debug ())
1288     stackdump (thread_context.ebp, 1, 1);
1289
1290   lock_process until_exit (true);
1291   if (hExeced || exit_state)
1292     myself.exit (rc);
1293
1294   /* Starve other threads in a vain attempt to stop them from doing something
1295      stupid. */
1296   SetThreadPriority (GetCurrentThread (), THREAD_PRIORITY_TIME_CRITICAL);
1297
1298   user_data->resourcelocks->Delete ();
1299   user_data->resourcelocks->Init ();
1300
1301   sigproc_printf ("about to call do_exit (%x)", rc);
1302   SetEvent (signal_arrived);
1303   do_exit (rc);
1304 }
1305
1306 void
1307 events_init ()
1308 {
1309   mask_sync.init ("mask_sync");
1310   windows_system_directory[0] = '\0';
1311   GetSystemDirectory (windows_system_directory, sizeof (windows_system_directory) - 2);
1312   char *end = strchr (windows_system_directory, '\0');
1313   if (end == windows_system_directory)
1314     api_fatal ("can't find windows system directory");
1315   if (end[-1] != '\\')
1316     {
1317       *end++ = '\\';
1318       *end = '\0';
1319     }
1320   windows_system_directory_length = end - windows_system_directory;
1321   debug_printf ("windows_system_directory '%s', windows_system_directory_length %d",
1322                 windows_system_directory, windows_system_directory_length);
1323 }
1324
1325 void
1326 events_terminate ()
1327 {
1328   exit_already = 1;
1329 }
1330
1331 int
1332 _cygtls::call_signal_handler ()
1333 {
1334   int this_sa_flags = 0;
1335   /* Call signal handler.  */
1336   while (sig)
1337     {
1338       lock ();
1339       this_sa_flags = sa_flags;
1340       int thissig = sig;
1341
1342       pop ();
1343       reset_signal_arrived ();
1344       sigset_t this_oldmask = set_process_mask_delta ();
1345       int this_errno = saved_errno;
1346       sig = 0;
1347       unlock ();        // make sure synchronized
1348       incyg = 0;
1349       if (!(this_sa_flags & SA_SIGINFO))
1350         {
1351           void (*sigfunc) (int) = func;
1352           sigfunc (thissig);
1353         }
1354       else
1355         {
1356           siginfo_t thissi = infodata;
1357           void (*sigact) (int, siginfo_t *, void *) = (void (*) (int, siginfo_t *, void *)) func;
1358           /* no ucontext_t information provided yet */
1359           sigact (thissig, &thissi, NULL);
1360         }
1361       incyg = 1;
1362       set_signal_mask (this_oldmask, myself->getsigmask ());
1363       if (this_errno >= 0)
1364         set_errno (this_errno);
1365     }
1366
1367   return this_sa_flags & SA_RESTART;
1368 }
1369
1370 extern "C" void __stdcall
1371 reset_signal_arrived ()
1372 {
1373   // NEEDED? WaitForSingleObject (signal_arrived, 10);
1374   ResetEvent (signal_arrived);
1375   sigproc_printf ("reset signal_arrived");
1376   if (_my_tls.stackptr > _my_tls.stack)
1377     debug_printf ("stackptr[-1] %p", _my_tls.stackptr[-1]);
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 }