#include "sigproc.h"
#include "pinfo.h"
#include "cygerrno.h"
-#include "thread.h"
#include "perthread.h"
+#include "shared_info.h"
+#include "perprocess.h"
+#include "security.h"
char debugger_command[2 * MAX_PATH + 20];
extern void sigreturn ();
extern void sigdelayed ();
extern void siglast ();
-extern DWORD __sigfirst, __siglast;
};
+extern DWORD sigtid;
+
static BOOL WINAPI ctrl_c_handler (DWORD);
static void signal_exit (int) __attribute__ ((noreturn));
static char windows_system_directory[1024];
static NO_COPY muto *mask_sync = NULL;
HMODULE NO_COPY cygwin_hmodule;
-HANDLE NO_COPY console_handler_thread_waiter = NULL;
static const struct
{
sec_all.lpSecurityDescriptor = sec_all_nih.lpSecurityDescriptor =
get_null_sd ();
- /* Allocate the event needed for ctrl_c_handler synchronization with
- wait_sig. */
- if (!console_handler_thread_waiter)
- CreateEvent (&sec_none_nih, TRUE, TRUE, NULL);
(void) SetConsoleCtrlHandler (ctrl_c_handler, FALSE);
if (!SetConsoleCtrlHandler (ctrl_c_handler, TRUE))
system_printf ("SetConsoleCtrlHandler failed, %E");
/* This is the main stack frame info for this process. */
static NO_COPY stack_info thestack;
-signal_dispatch sigsave;
+static signal_dispatch sigsave;
/* Initialize everything needed to start iterating. */
void
static void
stackdump (EXCEPTION_RECORD *e, CONTEXT *in)
{
- char *p;
+ const char *p;
if (myself->progname[0])
{
/* write to progname.stackdump if possible */
}
if (!myself->progname[0]
+ || GetCurrentThreadId () == sigtid
|| (void *) myself->getsig (sig).sa_handler == (void *) SIG_DFL
|| (void *) myself->getsig (sig).sa_handler == (void *) SIG_IGN
|| (void *) myself->getsig (sig).sa_handler == (void *) SIG_ERR)
interruptible (DWORD pc, int testvalid = 0)
{
int res;
- if ((pc >= (DWORD) &__sigfirst) && (pc <= (DWORD) &__siglast))
+ MEMORY_BASIC_INFORMATION m;
+
+ memset (&m, 0, sizeof m);
+ if (!VirtualQuery ((LPCVOID) pc, &m, sizeof m))
+ sigproc_printf ("couldn't get memory info, pc %p, %E", pc);
+
+ char *checkdir = (char *) alloca (windows_system_directory_length + 4);
+ memset (checkdir, 0, sizeof (checkdir));
+
+# define h ((HMODULE) m.AllocationBase)
+ /* Apparently Windows 95 can sometimes return bogus addresses from
+ GetThreadContext. These resolve to an allocation base == 0.
+ These should *never* be treated as interruptible. */
+ if (!h || m.State != MEM_COMMIT)
+ res = 0;
+ else if (testvalid)
+ res = 1; /* All we wanted to know was if this was a valid module. */
+ else if (h == user_data->hmodule)
+ res = 1;
+ else if (h == cygwin_hmodule)
+ res = 0;
+ else if (!GetModuleFileName (h, checkdir, windows_system_directory_length + 2))
res = 0;
else
- {
- MEMORY_BASIC_INFORMATION m;
- memset (&m, 0, sizeof m);
- if (!VirtualQuery ((LPCVOID) pc, &m, sizeof m))
- sigproc_printf ("couldn't get memory info, %E");
-
- char *checkdir = (char *) alloca (windows_system_directory_length + 4);
- memset (checkdir, 0, sizeof (checkdir));
-# define h ((HMODULE) m.AllocationBase)
- /* Apparently Windows 95 can sometimes return bogus addresses from
- GetThreadContext. These resolve to an allocation base == 0.
- These should *never* be treated as interruptible. */
- if (!h)
- res = 0;
- else if (testvalid)
- res = 1; /* All we wanted to know was if this was a valid module. */
- else if (h == user_data->hmodule)
- res = 1;
- else if (h == cygwin_hmodule)
- res = 0;
- else if (!GetModuleFileName (h, checkdir, windows_system_directory_length + 2))
- res = 0;
- else
- res = !strncasematch (windows_system_directory, checkdir,
- windows_system_directory_length);
- minimal_printf ("h %p", h);
-# undef h
- }
+ res = !strncasematch (windows_system_directory, checkdir,
+ windows_system_directory_length);
+ minimal_printf ("h %p", h);
+# undef h
minimal_printf ("interruptible %d", res);
return res;
SetThreadContext (myself->getthread2signal (), ctx); /* Restart the thread */
}
-void __cdecl
+void __stdcall
signal_fixup_after_fork ()
{
if (!sigsave.sig)
}
}
+void __stdcall
+signal_fixup_after_exec (bool isspawn)
+{
+ /* Set up child's signal handlers */
+ for (int i = 0; i < NSIG; i++)
+ {
+ myself->getsig(i).sa_mask = 0;
+ if (myself->getsig(i).sa_handler != SIG_IGN || isspawn)
+ myself->getsig(i).sa_handler = SIG_DFL;
+ }
+}
+
static int
interrupt_on_return (DWORD ebp, int sig, struct sigaction& siga, void *handler)
{
{
set_errno (e);
sigsave.saved_errno = e;
- debug_printf ("errno %d", e);
+ // sigproc_printf ("errno %d", e);
}
#define SUSPEND_TRIES 10000
int res;
int using_mainthread_frame;
+#if 0
mainthread.lock->acquire ();
+#endif
+
+ if (sigsave.sig)
+ goto set_pending;
if (mainthread.frame)
{
{
int i;
using_mainthread_frame = 0;
+#if 0
mainthread.lock->release ();
+#endif
hth = myself->getthread2signal ();
/* Suspend the thread which will receive the signal. But first ensure that
if (m->unstable () || m->owner () == mainthread.id)
goto owns_muto;
+#if 0
mainthread.lock->acquire ();
+#endif
if (mainthread.frame)
{
ebp = mainthread.frame; /* try to avoid a race */
using_mainthread_frame = 1;
goto next;
}
+#if 0
mainthread.lock->release ();
+#endif
cx.ContextFlags = CONTEXT_CONTROL | CONTEXT_INTEGER;
if (!GetThreadContext (hth, &cx))
}
next:
- if (hExeced != NULL || (!using_mainthread_frame && interruptible (cx.Eip)))
+ if (!using_mainthread_frame && interruptible (cx.Eip))
interrupt_now (&cx, sig, siga, handler);
else if (!interrupt_on_return (ebp, sig, siga, handler))
{
sigproc_printf ("ResumeThread returned %d", res);
}
+#if 0
mainthread.lock->release ();
+#endif
sigproc_printf ("returning %d", interrupted);
return interrupted;
if (type == CTRL_LOGOFF_EVENT)
return TRUE;
- /* Wait for sigproc_init to tell us that it's safe to send something.
- This event will always be in a signalled state when wait_sig is
- ready to process signals. */
- (void) WaitForSingleObject (console_handler_thread_waiter, 5000);
-
if ((type == CTRL_CLOSE_EVENT) || (type == CTRL_SHUTDOWN_EVENT))
/* Return FALSE to prevent an "End task" dialog box from appearing
for each Cygwin process window that's open when the computer
extern "C" void __stdcall
set_process_mask (sigset_t newmask)
{
- extern DWORD sigtid;
-
mask_sync->acquire (INFINITE);
sigset_t oldmask = myself->getsigmask ();
newmask &= ~SIG_NONMASKABLE;
while (ResumeThread (hMainThread) > 1)
;
/* process pending signals */
- sig_dispatch_pending ();
+ sig_dispatch_pending (1);
}
#if 0
sig |= 0x80;
}
sigproc_printf ("signal %d, about to call do_exit", sig);
- TerminateThread (hMainThread, 0);
- /* FIXME: This just works around the problem so that we don't attempt to
- use a resource lock when exiting. */
- user_data->resourcelocks->Delete ();
- user_data->resourcelocks->Init ();
signal_exit (sig);
/* Never returns */
}
static void
signal_exit (int rc)
{
- /* If the exception handler gets a trap, we could recurse awhile.
- If this is non-zero, skip the cleaning up and exit NOW. */
+ extern HANDLE hExeced;
rc = EXIT_SIGNAL | (rc << 8);
if (exit_already++)
- {
- /* We are going down - reset our process_state without locking. */
- myself->record_death ();
- ExitProcess (rc);
- }
+ myself->exit (rc);
+
+ /* We'd like to stop the main thread from executing but when we do that it
+ causes random, inexplicable hangs. So, instead, we set up the priority
+ of this thread really high so that it should do its thing and then exit. */
+ (void) SetThreadPriority (GetCurrentThread (), THREAD_PRIORITY_TIME_CRITICAL);
+ /* Unlock any main thread mutos since we're executing with prejudice. */
+ muto *m;
+ for (m = muto_start.next; m != NULL; m = m->next)
+ if (m->unstable () || m->owner () == mainthread.id)
+ m->reset ();
+
+ user_data->resourcelocks->Delete ();
+ user_data->resourcelocks->Init ();
+
+ if (hExeced)
+ TerminateProcess (hExeced, rc);
+
+ sigproc_printf ("about to call do_exit (%x)", rc);
do_exit (rc);
}
#define pid_offset (unsigned)(((_pinfo *)NULL)->pid)
extern "C" {
-static void __stdcall
-reset_signal_arrived () __attribute__ ((unused));
+static void __stdcall reset_signal_arrived () __attribute__ ((unused));
static void __stdcall
reset_signal_arrived ()
{
_sigreturn:
addl $4,%%esp
+ movl %%esp,%%ebp
+ addl $36,%%ebp
call _set_process_mask@4
popl %%eax # saved errno
testl %%eax,%%eax # Is it < 0
popl %%edx
popl %%edi
popl %%esi
+ popl %%ebp
popf
ret
_sigdelayed:
pushl %2 # original return address
pushf
+ pushl %%ebp
pushl %%esi
pushl %%edi
pushl %%edx
cmpl $0,_pending_signals
je 2f
-___sigfirst:
pushl $0
call _sig_dispatch_pending@4
-___siglast:
2: jmp *%5