4
0
mirror of git://sourceware.org/git/newlib-cygwin.git synced 2025-02-20 16:01:10 +08:00

* 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

@ -1,3 +1,30 @@
Mon Nov 6 01:04:35 2000 Christopher Faylor <cgf@cygnus.com>
* 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.
Sun Nov 5 13:46:23 2000 Christopher Faylor <cgf@cygnus.com>
* pinfo (wait_subproc): Son of neverending debug tweaking.

View File

@ -12,7 +12,7 @@ details. */
enum
{
PROC_MAGIC = 0xaf09f000,
PROC_MAGIC = 0xaf0af000,
PROC_FORK = PROC_MAGIC + 1,
PROC_EXEC = PROC_MAGIC + 2,
PROC_SPAWN = PROC_MAGIC + 3,
@ -38,6 +38,7 @@ public:
HANDLE console_h;
HANDLE parent_alive; // handle of thread used to track children
HANDLE parent;
HANDLE pppid_handle;
void *cygheap;
void *cygheap_max;
};

View File

@ -898,8 +898,9 @@ _dll_crt0 ()
case PROC_FORK:
case PROC_FORK1:
user_data->forkee = fork_info->cygpid;
case PROC_EXEC:
case PROC_SPAWN:
CloseHandle (fork_info->pppid_handle);
case PROC_EXEC:
{
child_proc_info = fork_info;
mypid = child_proc_info->cygpid;

View File

@ -228,7 +228,7 @@ newh ()
goto out;
/* All used up??? */
if ((hl = (handle_list *)malloc (sizeof *hl)) != NULL)
if ((hl = (handle_list *) malloc (sizeof *hl)) != NULL)
{
memset (hl, 0, sizeof (*hl));
hl->allocated = TRUE;
@ -248,6 +248,7 @@ add_handle (const char *func, int ln, HANDLE h, const char *name)
if ((hl = find_handle (h)))
{
hl = hl->next;
system_printf ("%s:%d - multiple attempts to add handle %s<%p>", func,
ln, name, h);
system_printf (" previously allocated by %s:%d(%s<%p>)",

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),

View File

@ -471,35 +471,12 @@ fork_parent (void *stack_here, HANDLE& hParent, dll *&first_dll, bool& load_dlls
system_printf ("couldn't create last_fork_proc, %E");
/* Fill in fields in the child's process table entry. */
forked->ppid = myself->pid;
forked->hProcess = pi.hProcess;
forked->dwProcessId = pi.dwProcessId;
forked->uid = myself->uid;
forked->gid = myself->gid;
forked->pgid = myself->pgid;
forked->sid = myself->sid;
forked->ctty = myself->ctty;
forked->umask = myself->umask;
forked->copysigs(myself);
forked->process_state |= PID_INITIALIZING |
(myself->process_state & PID_USETTY);
memcpy (forked->username, myself->username, MAX_USER_NAME);
if (myself->use_psid)
{
memcpy (forked->psid, myself->psid, MAX_SID_LEN);
forked->use_psid = 1;
}
memcpy (forked->logsrv, myself->logsrv, MAX_HOST_NAME);
memcpy (forked->domain, myself->domain, MAX_COMPUTERNAME_LENGTH+1);
forked->token = myself->token;
forked->impersonated = myself->impersonated;
forked->orig_uid = myself->orig_uid;
forked->orig_gid = myself->orig_gid;
forked->real_uid = myself->real_uid;
forked->real_gid = myself->real_gid;
strcpy (forked->root, myself->root);
forked->rootlen = myself->rootlen;
set_child_mmap_ptr (forked);
forked.remember ();
/* Wait for subproc to initialize itself. */
if (!sync_with_child(pi, subproc_ready, TRUE, "waiting for longjmp"))
@ -536,8 +513,6 @@ fork_parent (void *stack_here, HANDLE& hParent, dll *&first_dll, bool& load_dlls
goto cleanup;
}
forked.remember ();
/* Start thread, and wait for it to reload dlls. */
if (!resume_child (pi, forker_finished) ||
!sync_with_child (pi, subproc_ready, load_dlls, "child loading dlls"))

View File

@ -44,6 +44,9 @@ public:
/* Handle associated with initial Windows pid which started it all. */
HANDLE pid_handle;
/* Handle to the logical parent of this pid. */
HANDLE ppid_handle;
/* Parent process id. */
pid_t ppid;

View File

@ -235,7 +235,7 @@ proc_subproc (DWORD what, DWORD val)
if (!get_proc_lock (what, val)) // Serialize access to this function
{
sigproc_printf ("I am not ready");
system_printf ("couldn't get proc lock. Something is wrong.");
goto out1;
}
@ -253,6 +253,33 @@ proc_subproc (DWORD what, DWORD val)
0, 0, DUPLICATE_SAME_ACCESS))
system_printf ("Couldn't duplicate child handle for pid %d, %E", vchild->pid);
ProtectHandle1 (vchild->pid_handle, pid_handle);
if (!DuplicateHandle (hMainProc, hMainProc, vchild->hProcess, &vchild->ppid_handle,
0, TRUE, DUPLICATE_SAME_ACCESS))
system_printf ("Couldn't duplicate my handle<%p> for pid %d, %E", hMainProc, vchild->pid);
vchild->ppid = myself->pid;
vchild->gid = myself->gid;
vchild->pgid = myself->pgid;
vchild->sid = myself->sid;
vchild->ctty = myself->ctty;
vchild->umask = myself->umask;
vchild->orig_uid = myself->orig_uid;
vchild->orig_gid = myself->orig_gid;
vchild->real_uid = myself->real_uid;
vchild->real_gid = myself->real_gid;
vchild->impersonated = myself->impersonated;
if (myself->use_psid)
{
vchild->use_psid = 1;
memcpy (vchild->psid, myself->psid, MAX_SID_LEN);
}
memcpy (vchild->logsrv, myself->logsrv, MAX_HOST_NAME);
memcpy (vchild->domain, myself->domain, MAX_COMPUTERNAME_LENGTH+1);
memcpy (vchild->root, myself->root, MAX_PATH+1);
vchild->token = myself->token;
vchild->rootlen = myself->rootlen;
vchild->process_state |= PID_INITIALIZING | (myself->process_state & PID_USETTY);
sigproc_printf ("added pid %d to wait list, slot %d, winpid %p, handle %p",
vchild->pid, nchildren, vchild->dwProcessId,
vchild->hProcess);
@ -810,6 +837,7 @@ init_child_info (DWORD chtype, child_info *ch, pid_t pid, HANDLE subproc_ready)
ch->shared_h = cygwin_shared_h;
ch->console_h = console_shared_h;
ch->subproc_ready = subproc_ready;
ch->pppid_handle = myself->ppid_handle;
if (chtype != PROC_EXEC || !parent_alive)
ch->parent_alive = hwait_subproc;
else
@ -1100,7 +1128,7 @@ wait_sig (VOID *)
HANDLE catchem[] = {sigcatch_main, sigcatch_nonmain, sigcatch_nosync};
sigproc_printf ("Ready. dwProcessid %d", myself->dwProcessId);
for (;;)
for (int i = 0; ; i++)
{
DWORD rc = WaitForMultipleObjects (3, catchem, FALSE, sig_loop_wait);
@ -1128,7 +1156,8 @@ wait_sig (VOID *)
/* A sigcatch semaphore has been signaled. Scan the sigtodo
* array looking for any unprocessed signals.
*/
pending_signals = 0;
pending_signals = -1;
int saw_pending_signals = 0;
int saw_sigchld = 0;
int dispatched_sigchld = 0;
for (int sig = -__SIGOFFSET; sig < NSIG; sig++)
@ -1179,11 +1208,26 @@ wait_sig (VOID *)
}
/* Decremented too far. */
if (InterlockedIncrement (myself->getsigtodo(sig)) > 0)
pending_signals = 1;
saw_pending_signals = 1;
nextsig:
continue;
}
/* FIXME: The dispatched stuff probably isn't needed anymore. */
if (dispatched >= 0 && pending_signals < 0 && !saw_pending_signals)
{
pending_signals = 0;
/* FIXME FIXME FIXME FIXME FIXME
This is a real kludge designed to handle runaway processes who
missed a signal and never processed a signal handler. We have
to reset signal_arrived or stuff goes crazy. */
if (i >= 20)
{
i = 0;
ResetEvent (signal_arrived);
}
}
if (nzombies && saw_sigchld && !dispatched_sigchld)
proc_subproc (PROC_CLEARWAIT, 0);
/* Signal completion of signal handling depending on which semaphore
@ -1202,8 +1246,6 @@ wait_sig (VOID *)
break;
}
if (dispatched < 0)
pending_signals = 1;
sigproc_printf ("looping");
}
@ -1258,7 +1300,6 @@ wait_subproc (VOID *)
system_printf ("pid %d, dwProcessId %u, hProcess %p, progname '%s'",
pchildren[i - 1]->pid, pchildren[i - 1]->dwProcessId,
pchildren[i - 1]->hProcess, pchildren[i - 1]->progname);
Sleep (10000);
}
break;
}

View File

@ -707,22 +707,6 @@ skip_arg_parsing:
}
child->username[0] = '\0';
child->progname[0] = '\0';
child->ppid = myself->pid;
child->gid = myself->gid;
child->pgid = myself->pgid;
child->sid = myself->sid;
child->ctty = myself->ctty;
child->umask = myself->umask;
child->process_state |= PID_INITIALIZING;
if (myself->use_psid)
{
child->use_psid = 1;
memcpy (child->psid, myself->psid, MAX_SID_LEN);
}
memcpy (child->logsrv, myself->logsrv, MAX_HOST_NAME);
memcpy (child->domain, myself->domain, MAX_COMPUTERNAME_LENGTH+1);
memcpy (child->root, myself->root, MAX_PATH+1);
child->rootlen = myself->rootlen;
child->dwProcessId = pi.dwProcessId;
child->hProcess = pi.hProcess;
child.remember ();
@ -808,20 +792,17 @@ skip_arg_parsing:
{
int rc = 0;
HANDLE oldh = myself->hProcess;
HANDLE h = OpenProcess (PROCESS_ALL_ACCESS, FALSE,
parent->dwProcessId);
HANDLE h = myself->ppid_handle;
sigproc_printf ("parent handle %p, pid %d", h, parent->dwProcessId);
if (h == NULL && GetLastError () == ERROR_INVALID_PARAMETER)
rc = 1;
rc = 0;
else if (h)
{
ProtectHandle (h);
rc = DuplicateHandle (hMainProc, pi.hProcess,
h, &myself->hProcess, 0, FALSE,
DUPLICATE_SAME_ACCESS);
sigproc_printf ("%d = DuplicateHandle, oldh %p, newh %p",
rc, oldh, myself->hProcess);
ForceCloseHandle (h);
}
if (!rc)
{