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