* child_info.h (child_info): Add pppid_handle for closing the parent's of the

parent handle.
* dcrt0.cc (_dll_crt0): Close parent's parent handle when spawned or forked.
* debug.cc (add_handle): Correct erroneous reference to handle structure when
printing warning.
* exceptions.cc (interrupt_now): Always return 1.
(interrupt_on_return): Accept a sigthread argument.  Check to see if this
argument has been trashed prior to setting up the stack return.
(call_handler): Add a loop around attempts to dispatch signals to detect case
where interrupt_on_return fails.
(_sigdelayed): Set up a temporary frame pointer prior to calling stuff that
could trigger an interrupt or the stack walking code will be very confused.
* fork.cc (fork_parent): Move a lot of the setup of the child process into
proc_subproc.
* spawn.cc (spawn_guts): Ditto.  Use ppid_handle to contact logical parent when
reparenting.
* pinfo.h (_pinfo): Remember the logical handle of the parent process.
* sigproc.cc (proc_subproc): Record most stuff necessary for the _pinfo
structure that is inferrable from myself when adding children.
(wait_sig): Always set 'pending_signals' flag when about to kick off the signal
scanning loop.  Reset it only if there are no pending signals.
This commit is contained in:
Christopher Faylor
2000-11-06 06:36:32 +00:00
parent e0997f5a0f
commit dd11f11fae
9 changed files with 189 additions and 142 deletions

View File

@ -30,6 +30,7 @@ static int handle_exceptions (EXCEPTION_RECORD *, void *, CONTEXT *, void *);
extern void sigreturn ();
extern void sigdelayed ();
extern void siglast ();
extern DWORD __no_sig_start, __no_sig_end;
};
extern DWORD sigtid;
@ -627,12 +628,13 @@ interrupt_setup (int sig, struct sigaction& siga, void *handler,
sigsave.saved_errno = -1; // Flag: no errno to save
}
static void
static bool
interrupt_now (CONTEXT *ctx, int sig, struct sigaction& siga, void *handler)
{
interrupt_setup (sig, siga, handler, ctx->Eip, 0);
ctx->Eip = (DWORD) sigdelayed;
SetThreadContext (myself->getthread2signal (), ctx); /* Restart the thread */
return 1;
}
void __stdcall
@ -662,12 +664,13 @@ signal_fixup_after_exec (bool isspawn)
}
static int
interrupt_on_return (DWORD ebp, int sig, struct sigaction& siga, void *handler)
interrupt_on_return (sigthread *th, int sig, struct sigaction& siga, void *handler)
{
int i;
DWORD ebp = th->frame;
if (sigsave.sig)
return 0; /* Already have a signal stacked up */
if (!ebp)
return 0;
thestack.init (ebp); /* Initialize from the input CONTEXT */
for (i = 0; i < 32 && thestack++ ; i++)
@ -677,12 +680,16 @@ interrupt_on_return (DWORD ebp, int sig, struct sigaction& siga, void *handler)
if (*addr_retaddr == thestack.sf.AddrReturn.Offset)
{
interrupt_setup (sig, siga, handler, *addr_retaddr, addr_retaddr);
if (ebp != th->frame)
{
sigsave.sig = 0;
break;
}
*addr_retaddr = (DWORD) sigdelayed;
}
return 1;
}
api_fatal ("couldn't send signal %d", sig);
return 0;
}
@ -700,11 +707,10 @@ static int
call_handler (int sig, struct sigaction& siga, void *handler)
{
CONTEXT cx;
int interrupted = 1;
bool interrupted = 0;
HANDLE hth = NULL;
DWORD ebp;
int res;
int using_mainthread_frame;
sigthread *th;
#if 0
mainthread.lock->acquire ();
@ -713,98 +719,101 @@ call_handler (int sig, struct sigaction& siga, void *handler)
if (sigsave.sig)
goto set_pending;
if (mainthread.frame)
for (int i = 0; !interrupted && i < 10; i++)
{
ebp = mainthread.frame;
using_mainthread_frame = 1;
}
else
{
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
this thread doesn't have any mutos. (FIXME: Someday we should just grab
all of the mutos rather than checking for them)
For Windows 95, we also have to ensure that the addresses returned by GetThreadContext
are valid.
If one of these conditions is not true we loop for a fixed number of times
since we don't want to stall the signal handler. FIXME: Will this result in
noticeable delays?
If the thread is already suspended (which can occur when a program is stopped) then
just queue the signal. */
for (i = 0; i < SUSPEND_TRIES; i++)
if (mainthread.frame)
th = &mainthread;
else
{
sigproc_printf ("suspending mainthread");
res = SuspendThread (hth);
muto *m;
/* FIXME: Make multi-thread aware */
for (m = muto_start.next; m != NULL; m = m->next)
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
int i;
th = NULL;
#if 0
mainthread.lock->release ();
#endif
#endif
cx.ContextFlags = CONTEXT_CONTROL | CONTEXT_INTEGER;
if (!GetThreadContext (hth, &cx))
hth = myself->getthread2signal ();
/* Suspend the thread which will receive the signal. But first ensure that
this thread doesn't have any mutos. (FIXME: Someday we should just grab
all of the mutos rather than checking for them)
For Windows 95, we also have to ensure that the addresses returned by GetThreadContext
are valid.
If one of these conditions is not true we loop for a fixed number of times
since we don't want to stall the signal handler. FIXME: Will this result in
noticeable delays?
If the thread is already suspended (which can occur when a program is stopped) then
just queue the signal. */
for (i = 0; i < SUSPEND_TRIES; i++)
{
system_printf ("couldn't get context of main thread, %E");
goto out;
sigproc_printf ("suspending mainthread");
res = SuspendThread (hth);
/* Just set pending if thread is already suspended */
if (res)
goto set_pending;
muto *m;
/* FIXME: Make multi-thread aware */
for (m = muto_start.next; m != NULL; m = m->next)
if (m->unstable () || m->owner () == mainthread.id)
goto owns_muto;
#if 0
mainthread.lock->acquire ();
#endif
if (mainthread.frame)
{
th = &mainthread;
goto next;
}
#if 0
mainthread.lock->release ();
#endif
cx.ContextFlags = CONTEXT_CONTROL | CONTEXT_INTEGER;
if (!GetThreadContext (hth, &cx))
{
system_printf ("couldn't get context of main thread, %E");
goto out;
}
if (interruptible (cx.Eip, 1))
break;
sigproc_printf ("suspended thread in a strange state pc %p, sp %p",
cx.Eip, cx.Esp);
goto resume_thread;
owns_muto:
sigproc_printf ("suspended thread owns a muto (%s)", m->name);
resume_thread:
ResumeThread (hth);
Sleep (0);
}
if (interruptible (cx.Eip, 1))
break;
sigproc_printf ("suspended thread in a strange state pc %p, sp %p",
cx.Eip, cx.Esp);
goto resume_thread;
owns_muto:
sigproc_printf ("suspended thread owns a muto (%s)", m->name);
if (res)
if (i >= SUSPEND_TRIES)
goto set_pending;
resume_thread:
ResumeThread (hth);
Sleep (0);
sigproc_printf ("SuspendThread returned %d", res);
}
if (i >= SUSPEND_TRIES)
goto set_pending;
sigproc_printf ("SuspendThread returned %d", res);
ebp = cx.Ebp;
next:
if (th)
interrupted = interrupt_on_return (th, sig, siga, handler);
else if (interruptible (cx.Eip))
interrupted = interrupt_now (&cx, sig, siga, handler);
else
break;
}
next:
if (!using_mainthread_frame && interruptible (cx.Eip))
interrupt_now (&cx, sig, siga, handler);
else if (!interrupt_on_return (ebp, sig, siga, handler))
set_pending:
if (!interrupted)
{
set_pending:
pending_signals = 1; /* FIXME: Probably need to be more tricky here */
sig_set_pending (sig);
interrupted = 0;
sigproc_printf ("couldn't send signal %d", sig);
}
if (interrupted)
else
{
res = SetEvent (signal_arrived); // For an EINTR case
sigproc_printf ("armed signal_arrived %p, res %d", signal_arrived, res);
@ -882,6 +891,9 @@ set_process_mask (sigset_t newmask)
mask_sync->release ();
if (oldmask != newmask && GetCurrentThreadId () != sigtid)
sig_dispatch_pending ();
else
sigproc_printf ("not calling sig_dispatch_pending. sigtid %p current %p",
sigtid, GetCurrentThreadId ());
return;
}
@ -1099,7 +1111,7 @@ __asm__ volatile ("
.text
_sigreturn:
addl $4,%%esp
addl $4,%%esp # Remove argument
movl %%esp,%%ebp
addl $36,%%ebp
call _set_process_mask@4
@ -1118,6 +1130,7 @@ _sigreturn:
popf
ret
__no_sig_start:
_sigdelayed:
pushl %2 # original return address
pushf
@ -1132,6 +1145,8 @@ _sigdelayed:
pushl %3 # oldmask
pushl %4 # signal argument
pushl $_sigreturn
pushl %%ebp
movl %%esp,%%esp
call _reset_signal_arrived@0
movl $0,%0
@ -1141,7 +1156,9 @@ _sigdelayed:
pushl $0
call _sig_dispatch_pending@4
2: jmp *%5
2: popl %%ebp
jmp *%5
__no_sig_end:
" : "=m" (sigsave.sig) : "m" (&_impure_ptr->_errno),
"g" (sigsave.retaddr), "g" (sigsave.oldmask), "g" (sigsave.sig),