3 Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
4 2005, 2006, 2007, 2008, 2009, 2010, 2011 Red Hat, Inc.
6 This file is part of Cygwin.
8 This software is a copyrighted work licensed under the terms of the
9 Cygwin license. Please consult the file "CYGWIN_LICENSE" for
14 #include "miscfuncs.h"
25 #include "shared_info.h"
26 #include "perprocess.h"
31 #include "child_info.h"
33 #include "exception.h"
36 #define CALL_HANDLER_RETRY_OUTER 10
37 #define CALL_HANDLER_RETRY_INNER 10
39 char debugger_command
[2 * NT_MAX_PATH
+ 20];
42 extern void sigdelayed ();
45 static BOOL WINAPI
ctrl_c_handler (DWORD
);
47 /* This is set to indicate that we have already exited. */
49 static NO_COPY
int exit_already
= 0;
50 static muto NO_COPY mask_sync
;
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
) },
91 /* Initialization code. */
94 init_console_handler (bool install_handler
)
98 SetConsoleCtrlHandler (ctrl_c_handler
, FALSE
);
99 SetConsoleCtrlHandler (NULL
, FALSE
);
101 res
= SetConsoleCtrlHandler (ctrl_c_handler
, TRUE
);
103 res
= SetConsoleCtrlHandler (NULL
, TRUE
);
105 system_printf ("SetConsoleCtrlHandler failed, %E");
109 error_start_init (const char *buf
)
113 debugger_command
[0] = '\0';
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
, '\\'))
123 __small_sprintf (debugger_command
, "%s \"%s\"", buf
, pgm
);
127 open_stackdumpfile ()
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
132 if (myself
->progname
[0] && cygheap
->cwd
.get_handle ())
135 /* write to progname.stackdump if possible */
136 if (!myself
->progname
[0])
138 else if ((p
= wcsrchr (myself
->progname
, L
'\\')))
141 p
= myself
->progname
;
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
);
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
))
163 if (!myself
->cygstarted
)
164 system_printf ("Dumping stack trace to %S", &ucore
);
166 debug_printf ("Dumping stack trace to %S", &ucore
);
167 SetStdHandle (STD_ERROR_HANDLE
, h
);
172 /* Utilities for dumping the stack, etc. */
175 dump_exception (EXCEPTION_RECORD
*e
, CONTEXT
*in
)
177 const char *exception_name
= NULL
;
181 for (int i
= 0; status_info
[i
].name
; i
++)
183 if (status_info
[i
].code
== e
->ExceptionCode
)
185 exception_name
= status_info
[i
].name
;
192 small_printf ("Exception: %s at eip=%08x\r\n", exception_name
, in
->Eip
);
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
);
203 /* A class for manipulating the stack. */
206 int walk (); /* Uses the "old" method */
207 char *next_offset () {return *((char **) sf
.AddrFrame
.Offset
);}
211 STACKFRAME sf
; /* For storing the stack information */
212 void init (DWORD
, bool, bool); /* Called the first time that stack info is needed */
214 /* Postfix ++ iterates over the stack, returning zero when nothing is left. */
215 int operator ++(int) { return walk (); }
218 /* The number of parameters used in STACKFRAME */
219 #define NPARAMS (sizeof (thestack.sf.Params) / sizeof (thestack.sf.Params[0]))
221 /* This is the main stack frame info for this process. */
222 static NO_COPY stack_info thestack
;
224 /* Initialize everything needed to start iterating. */
226 stack_info::init (DWORD ebp
, bool wantargs
, bool goodframe
)
228 # define debp ((DWORD *) ebp)
229 memset (&sf
, 0, sizeof (sf
));
231 sf
.AddrFrame
.Offset
= ebp
;
235 sf
.AddrFrame
.Offset
= (DWORD
) &dummy_frame
;
237 sf
.AddrReturn
.Offset
= debp
[1];
238 sf
.AddrFrame
.Mode
= AddrModeFlat
;
243 extern "C" void _cygwin_exit_return ();
245 /* Walk the stack by looking at successive stored 'bp' frames.
246 This is not foolproof. */
252 if ((void (*) ()) sf
.AddrPC
.Offset
== _cygwin_exit_return
)
253 return 0; /* stack frames are exhausted */
255 if (((ebp
= (char **) next_offset ()) == NULL
) || (ebp
>= (char **) cygwin_hmodule
))
258 sf
.AddrFrame
.Offset
= (DWORD
) ebp
;
259 sf
.AddrPC
.Offset
= sf
.AddrReturn
.Offset
;
261 /* The return address always follows the stack pointer */
262 sf
.AddrReturn
.Offset
= (DWORD
) *++ebp
;
266 unsigned nparams
= NPARAMS
;
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)
276 for (unsigned i
= 1; i
< nparams
; i
++)
277 sf
.Params
[i
] = (DWORD
) *++ebp
;
284 stackdump (DWORD ebp
, PCONTEXT in
, EXCEPTION_RECORD
*e
)
286 static bool already_dumped
;
288 if (already_dumped
|| cygheap
->rlim_core
== 0Ul)
290 already_dumped
= true;
291 open_stackdumpfile ();
294 dump_exception (e
, in
);
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
++)
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");
308 small_printf ("End of stack trace%s\n",
309 i
== 16 ? " (more stack frames may be present)" : "");
313 _cygtls::inside_kernel (CONTEXT
*cx
)
316 MEMORY_BASIC_INFORMATION m
;
318 if (!isinitialized ())
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
);
325 size_t size
= (windows_system_directory_length
+ 6) * sizeof (WCHAR
);
326 PWCHAR checkdir
= (PWCHAR
) alloca (size
);
327 memset (checkdir
, 0, size
);
329 # define h ((HMODULE) m.AllocationBase)
330 if (!h
|| m
.State
!= MEM_COMMIT
) /* Be defensive */
332 else if (h
== user_data
->hmodule
)
334 else if (!GetModuleFileNameW (h
, checkdir
, windows_system_directory_length
+ 6))
338 /* Skip potential long path prefix. */
339 if (!wcsncmp (checkdir
, L
"\\\\?\\", 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;
348 sigproc_printf ("pc %p, h %p, inside_kernel %d", cx
->Eip
, h
, res
);
353 /* Temporary (?) function for external callers to get a stack dump */
358 c
.ContextFlags
= CONTEXT_FULL
;
359 GetThreadContext (GetCurrentThread (), &c
);
363 #define TIME_TO_WAIT_FOR_DEBUGGER 10000
366 try_to_debug (bool waitloop
)
368 debug_printf ("debugger_command '%s'", debugger_command
);
369 if (*debugger_command
== '\0')
371 if (being_debugged ())
373 extern void break_here ();
378 __small_sprintf (strchr (debugger_command
, '\0'), " %u", GetCurrentProcessId ());
380 LONG prio
= GetThreadPriority (GetCurrentThread ());
381 SetThreadPriority (GetCurrentThread (), THREAD_PRIORITY_HIGHEST
);
382 PROCESS_INFORMATION pi
= {NULL
, 0, 0, 0};
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
;
390 /* FIXME: need to know handles of all running threads to
391 suspend_all_threads_except (current_thread_id);
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. */
398 lock_ttys::release ();
400 /* prevent recursive exception handling */
401 PWCHAR rawenv
= GetEnvironmentStringsW () ;
402 for (PWCHAR p
= rawenv
; *p
!= L
'\0'; p
= wcschr (p
, L
'\0') + 1)
404 if (wcsncmp (p
, L
"CYGWIN=", wcslen (L
"CYGWIN=")) == 0)
406 PWCHAR q
= wcsstr (p
, L
"error_start") ;
407 /* replace 'error_start=...' with '_rror_start=...' */
411 SetEnvironmentVariableW (L
"CYGWIN", p
+ wcslen (L
"CYGWIN=")) ;
417 console_printf ("*** starting debugger for pid %u, tid %u\n",
418 cygwin_pid (GetCurrentProcessId ()), GetCurrentThreadId ());
420 WCHAR dbg_cmd
[strlen(debugger_command
)];
421 sys_mbstowcs (dbg_cmd
, strlen(debugger_command
) + 1, debugger_command
);
422 dbg
= CreateProcessW (NULL
,
427 CREATE_NEW_CONSOLE
| CREATE_NEW_PROCESS_GROUP
,
434 system_printf ("Failed to start debugger, %E");
439 SetThreadPriority (GetCurrentThread (), THREAD_PRIORITY_IDLE
);
440 while (!being_debugged ())
445 console_printf ("*** continuing pid %u from debugger call (%d)\n",
446 cygwin_pid (GetCurrentProcessId ()), dbg
);
448 SetThreadPriority (GetCurrentThread (), prio
);
452 extern "C" DWORD __stdcall
RtlUnwind (void *, void *, void *, DWORD
);
453 static void __stdcall
rtl_unwind (exception_list
*, PEXCEPTION_RECORD
) __attribute__ ((noinline
, regparm (3)));
455 rtl_unwind (exception_list
*frame
, PEXCEPTION_RECORD e
)
465 call _RtlUnwind@16 \n\
470 ": : "r" (frame
), "r" (e
));
473 /* Main exception handler. */
475 extern exception_list
*_except_list
asm ("%fs:0");
478 exception::handle (EXCEPTION_RECORD
*e
, exception_list
*frame
, CONTEXT
*in
, void *)
480 static bool NO_COPY debugging
;
481 static int NO_COPY recursed
;
482 _cygtls
& me
= _my_tls
;
484 if (debugging
&& ++debugging
< 500000)
486 SetThreadPriority (hMainThread
, THREAD_PRIORITY_NORMAL
);
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
)
496 si
.si_code
= SI_KERNEL
;
497 /* Coerce win32 value to posix value. */
498 switch (e
->ExceptionCode
)
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
;
507 case STATUS_FLOAT_INEXACT_RESULT
:
508 si
.si_signo
= SIGFPE
;
509 si
.si_code
= FPE_FLTRES
;
511 case STATUS_FLOAT_OVERFLOW
:
512 si
.si_signo
= SIGFPE
;
513 si
.si_code
= FPE_FLTOVF
;
515 case STATUS_FLOAT_UNDERFLOW
:
516 si
.si_signo
= SIGFPE
;
517 si
.si_code
= FPE_FLTUND
;
519 case STATUS_INTEGER_DIVIDE_BY_ZERO
:
520 si
.si_signo
= SIGFPE
;
521 si
.si_code
= FPE_INTDIV
;
523 case STATUS_INTEGER_OVERFLOW
:
524 si
.si_signo
= SIGFPE
;
525 si
.si_code
= FPE_INTOVF
;
528 case STATUS_ILLEGAL_INSTRUCTION
:
529 si
.si_signo
= SIGILL
;
530 si
.si_code
= ILL_ILLOPC
;
533 case STATUS_PRIVILEGED_INSTRUCTION
:
534 si
.si_signo
= SIGILL
;
535 si
.si_code
= ILL_PRVOPC
;
538 case STATUS_NONCONTINUABLE_EXCEPTION
:
539 si
.si_signo
= SIGILL
;
540 si
.si_code
= ILL_ILLADR
;
544 si
.si_signo
= SIGALRM
;
547 case STATUS_GUARD_PAGE_VIOLATION
:
548 si
.si_signo
= SIGBUS
;
549 si
.si_code
= BUS_OBJERR
;
552 case STATUS_DATATYPE_MISALIGNMENT
:
553 si
.si_signo
= SIGBUS
;
554 si
.si_code
= BUS_ADRALN
;
557 case STATUS_ACCESS_VIOLATION
:
558 switch (mmap_is_attached_or_noreserve ((void *)e
->ExceptionInformation
[1],
561 case MMAP_NORESERVE_COMMITED
:
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
;
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
;
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
;
586 case STATUS_CONTROL_C_EXIT
:
587 si
.si_signo
= SIGINT
;
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
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. */
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
);
608 bool masked
= !!(me
.sigmask
& SIGTOMASK (si
.si_signo
));
610 syscall_printf ("signal %d, masked %p", si
.si_signo
,
611 global_sigs
[si
.si_signo
].sa_mask
);
613 debug_printf ("In cygwin_except_handler calling %p",
614 global_sigs
[si
.si_signo
].sa_handler
);
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
)
625 me
.andreas
->leave (); /* Return from a "san" caught fault */
627 me
.copy_context (in
);
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
;
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
)
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
)
646 system_printf ("Exception: %s", status_info
[i
].name
);
650 /* Another exception could happen while tracing or while exiting.
651 Only do this once. */
653 system_printf ("Error while dumping state (probably corrupted stack)");
656 if (try_to_debug (0))
662 rtl_unwind (frame
, e
);
663 if (cygheap
->rlim_core
> 0UL)
664 stackdump ((DWORD
) ebp
, in
, e
);
667 if (e
->ExceptionCode
== STATUS_ACCESS_VIOLATION
)
670 if (si
.si_code
== SEGV_ACCERR
) /* Address present */
672 if (e
->ExceptionInformation
[0]) /* Write access */
674 if (!me
.inside_kernel (in
)) /* User space */
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));
683 /* Flag signal + core dump */
684 me
.signal_exit ((cygheap
->rlim_core
> 0UL ? 0x80 : 0) | si
.si_signo
);
687 si
.si_addr
= (si
.si_signo
== SIGSEGV
|| si
.si_signo
== SIGBUS
688 ? (void *) e
->ExceptionInformation
[1]
690 si
.si_errno
= si
.si_pid
= si
.si_uid
= 0;
692 sig_send (NULL
, si
, &me
); // Signal myself
694 e
->ExceptionFlags
= 0;
698 /* Utilities to call a user supplied exception handler. */
700 #define SIG_NONMASKABLE (SIGTOMASK (SIGKILL) | SIGTOMASK (SIGSTOP))
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.
710 handle_sigsuspend (sigset_t tempmask
)
712 sigset_t oldmask
= _my_tls
.sigmask
; // Remember for restoration
714 set_signal_mask (tempmask
, _my_tls
.sigmask
);
715 sigproc_printf ("oldmask %p, newmask %p", oldmask
, tempmask
);
717 pthread_testcancel ();
718 cancelable_wait (NULL
, NULL
, cw_cancel
| cw_cancel_self
| cw_sig_eintr
);
720 set_sig_errno (EINTR
); // Per POSIX
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. */
726 _my_tls
.deltamask
|= SIG_NONMASKABLE
;
727 _my_tls
.oldmask
= oldmask
; // Will be restored by signal handler
731 extern DWORD exec_exit
; // Possible exit value for exec
735 sig_handle_tty_stop (int sig
)
738 /* Silently ignore attempts to suspend if there is no accommodating
739 cygwin parent to deal with this behavior. */
740 if (!myself
->cygstarted
)
742 myself
->process_state
&= ~PID_STOPPED
;
746 myself
->stopsig
= sig
;
747 myself
->alert_parent (sig
);
748 sigproc_printf ("process %d stopped by signal %d", myself
->pid
, sig
);
751 switch (cancelable_wait (sigCONT
, NULL
, cw_sig_eintr
))
754 case WAIT_OBJECT_0
+ 1:
755 myself
->stopsig
= SIGCONT
;
756 myself
->alert_parent (SIGCONT
);
759 api_fatal ("WaitSingleObject failed, %E");
767 _cygtls::interrupt_now (CONTEXT
*cx
, int sig
, void *handler
,
768 struct sigaction
& siga
)
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
))
780 push ((__stack_t
) cx
->Eip
);
781 interrupt_setup (sig
, handler
, siga
);
783 SetThreadContext (*this, cx
); /* Restart the thread in a new location */
790 _cygtls::interrupt_setup (int sig
, void *handler
, struct sigaction
& siga
)
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
)
802 myself
->process_state
|= PID_STOPPED
;
805 this->sig
= sig
; // Should always be last thing set to avoid a race
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
,
823 extern "C" void __stdcall
824 set_sig_errno (int e
)
826 *_my_tls
.errno_addr
= e
;
827 _my_tls
.saved_errno
= e
;
830 static int setup_handler (int, void *, struct sigaction
&, _cygtls
*tls
)
831 __attribute__((regparm(3)));
833 setup_handler (int sig
, void *handler
, struct sigaction
& siga
, _cygtls
*tls
)
836 bool interrupted
= false;
840 sigproc_printf ("trying to send signal %d but signal %d already armed",
845 for (int n
= 0; n
< CALL_HANDLER_RETRY_OUTER
; n
++)
847 for (int i
= 0; i
< CALL_HANDLER_RETRY_INNER
; i
++)
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
);
861 HANDLE hth
= (HANDLE
) *tls
;
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. */
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 */
876 cx
.ContextFlags
= CONTEXT_CONTROL
| CONTEXT_INTEGER
;
877 if (!GetThreadContext (hth
, &cx
))
878 sigproc_printf ("couldn't get context of thread, %E");
880 interrupted
= tls
->interrupt_now (&cx
, sig
, handler
, siga
);
883 res
= ResumeThread (hth
);
887 sigproc_printf ("couldn't interrupt. trying again.");
890 /* Hit here if we couldn't deliver the signal. Take a more drastic
891 action before trying again. */
896 sigproc_printf ("signal %d %sdelivered", sig
, interrupted
? "" : "not ");
901 has_visible_window_station ()
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
,
916 && (uof
.dwFlags
& WSF_VISIBLE
))
921 /* Keyboard interrupt handler. */
923 ctrl_c_handler (DWORD type
)
925 static bool saw_close
;
927 if (!cygwin_finished_initializing
)
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
);
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
);
943 if (type
== CTRL_C_EVENT
|| type
== CTRL_BREAK_EVENT
)
944 proc_subproc (PROC_KILLFORKED
, 0);
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. */
951 if (type
== CTRL_SHUTDOWN_EVENT
)
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
958 sig_send (NULL
, SIGTERM
);
963 if (myself
->ctty
!= -1)
965 if (type
== CTRL_CLOSE_EVENT
)
967 sig_send (NULL
, SIGHUP
);
971 if (!saw_close
&& type
== CTRL_LOGOFF_EVENT
)
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
979 if (global_sigs
[SIGHUP
].sa_handler
!= SIG_DFL
)
981 sig_send (myself_nowait
, SIGHUP
);
988 if (ch_spawn
.set_saw_ctrl_c ())
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 ())))
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. */
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)
1011 t
->last_ctrl_c
= GetTickCount ();
1012 killsys (-myself
->pid
, sig
);
1013 t
->last_ctrl_c
= GetTickCount ();
1020 /* Function used by low level sig wrappers. */
1021 extern "C" void __stdcall
1022 set_process_mask (sigset_t newmask
)
1024 set_signal_mask (newmask
, _my_tls
.sigmask
);
1030 /* check that sig is in right range */
1031 if (sig
< 0 || sig
>= NSIG
)
1034 syscall_printf ("signal %d out of range", sig
);
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 ();
1048 /* check that sig is in right range */
1049 if (sig
< 0 || sig
>= NSIG
)
1052 syscall_printf ("signal %d out of range", sig
);
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 ();
1063 extern "C" _sig_func_ptr
1064 sigset (int sig
, _sig_func_ptr func
)
1066 sig_dispatch_pending ();
1069 /* check that sig is in right range */
1070 if (sig
< 0 || sig
>= NSIG
|| sig
== SIGKILL
|| sig
== SIGSTOP
)
1073 syscall_printf ("SIG_ERR = sigset (%d, %p)", sig
, func
);
1074 return (_sig_func_ptr
) SIG_ERR
;
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
))
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
);
1091 /* No error checking. The test which could return SIG_ERR has already
1094 sigdelset (&mask
, sig
);
1096 set_signal_mask (mask
, _my_tls
.sigmask
);
1097 mask_sync
.release ();
1104 return sigset (sig
, SIG_IGN
) == SIG_ERR
? -1 : 0;
1107 /* Update the signal mask for this process and return the old mask.
1108 Called from sigdelayed */
1110 set_process_mask_delta ()
1112 mask_sync
.acquire (INFINITE
);
1113 sigset_t newmask
, oldmask
;
1115 if (_my_tls
.deltamask
& SIG_NONMASKABLE
)
1116 oldmask
= _my_tls
.oldmask
; /* from handle_sigsuspend */
1118 oldmask
= _my_tls
.sigmask
;
1119 newmask
= (oldmask
| _my_tls
.deltamask
) & ~SIG_NONMASKABLE
;
1120 sigproc_printf ("oldmask %p, newmask %p, deltamask %p", oldmask
, newmask
,
1122 _my_tls
.sigmask
= newmask
;
1123 mask_sync
.release ();
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
)
1133 if (&_my_tls
== _sig_tls
)
1134 small_printf ("********* waiting in signal thread\n");
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
,
1143 sig_dispatch_pending (true);
1144 mask_sync
.release ();
1148 sigpacket::process ()
1151 struct sigaction dummy
= global_sigs
[SIGSTOP
];
1153 if (si
.si_signo
!= SIGCONT
)
1154 continue_now
= false;
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
);
1167 switch (si
.si_signo
)
1174 cygheap
->ctty
->sigflush ();
1182 sigproc_printf ("signal %d processing", si
.si_signo
);
1183 struct sigaction
& thissig
= global_sigs
[si
.si_signo
];
1185 myself
->rusage_self
.ru_nsignals
++;
1189 if (!have_execed
|| (void *) thissig
.sa_handler
== (void *) SIG_IGN
)
1190 handler
= (void *) thissig
.sa_handler
;
1196 _cygtls
*use_tls
= tls
?: _main_tls
;
1197 sigproc_printf ("tls %p, use_tls %p", tls
, use_tls
);
1199 if (si
.si_signo
== SIGKILL
)
1201 if (si
.si_signo
== SIGSTOP
)
1203 sig_clear (SIGCONT
);
1207 bool insigwait_mask
;
1208 if ((masked
= ISSTATE (myself
, PID_STOPPED
)))
1209 insigwait_mask
= false;
1211 insigwait_mask
= sigismember (&tls
->sigwait_mask
, si
.si_signo
);
1212 else if (!(tls
= _cygtls::find_tls (si
.si_signo
)))
1213 insigwait_mask
= false;
1217 insigwait_mask
= true;
1221 goto thread_specific
;
1224 /* nothing to do */;
1225 else if (sigismember (mask
, si
.si_signo
))
1228 masked
= sigismember (&tls
->sigmask
, si
.si_signo
);
1232 sigproc_printf ("signal %d blocked", si
.si_signo
);
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
);
1241 if (handler
== (void *) SIG_DFL
)
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
)
1248 sigproc_printf ("default signal %d ignored", si
.si_signo
);
1250 SetEvent (use_tls
->signal_arrived
);
1254 if (si
.si_signo
== SIGTSTP
|| si
.si_signo
== SIGTTIN
|| si
.si_signo
== SIGTTOU
)
1260 if (handler
== (void *) SIG_IGN
)
1262 sigproc_printf ("signal %d ignored", si
.si_signo
);
1266 if (handler
== (void *) SIG_ERR
)
1269 use_tls
->set_siginfo (this);
1273 /* Eat multiple attempts to STOP */
1274 if (ISSTATE (myself
, PID_STOPPED
))
1276 handler
= (void *) sig_handle_tty_stop
;
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
);
1288 sigproc_printf ("returning %d", rc
);
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
);
1300 use_tls
->signal_exit (si
.si_signo
); /* never returns */
1306 mask_sync
.init ("mask_sync");
1316 _cygtls::call_signal_handler ()
1318 int this_sa_flags
= SA_RESTART
;
1324 else if (this != _main_tls
)
1327 if (_main_tls
->sig
&& _main_tls
->incyg
)
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
;
1338 _main_tls
->unlock ();
1343 debug_only_printf ("dealing with signal %d", sig
);
1344 this_sa_flags
= sa_flags
;
1346 void (*thisfunc
) (int) = func
;
1348 sigset_t this_oldmask
= set_process_mask_delta ();
1349 int this_errno
= saved_errno
;
1351 unlock (); // make sure synchronized
1352 if (!(this_sa_flags
& SA_SIGINFO
))
1354 void (*sigfunc
) (int) = thisfunc
;
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 */
1364 sigact (thissig
, &thissi
, NULL
);
1367 set_signal_mask (this_oldmask
, _my_tls
.sigmask
);
1368 if (this_errno
>= 0)
1369 set_errno (this_errno
);
1373 return this_sa_flags
& SA_RESTART
|| (this != _main_tls
);
1377 _cygtls::copy_context (CONTEXT
*c
)
1379 memcpy (&thread_context
, c
, (&thread_context
._internal
- (unsigned char *) &thread_context
));
1383 _cygtls::signal_debugger (int sig
)
1385 if (isinitialized () && being_debugged ())
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
);