Throughout use myself->ppid_handle rather than parent_alive.

* child_info.h (child_info): Eliminate parent_alive.
* dcrt0.cc (dll_crt0_1): Call fork_init for debugging pid creation.
* fork.cc (fork_child): Reflect change to fixup_mmaps_after_fork arguments.
(slow_pid_reuse): New function to grab last 'n' pids to prevent pid reuse.
(fork_parent): Move last_fork_proc into slow_pid_reuse.  Handle fork_pids
debugging.  Eliminate unnecessary call to set_child_mmap_ptr.
(fork_init): New debugging function.
* mmap.cc (fixup_mmaps_after_fork): Renamed from recreate_mmaps_after_fork.
Rely on copied data after a fork.
(set_child_mmap_ptr): Eliminate.
* pinfo.h (_pinfo): Eliminate parent_alive, mmap_ptr and reflect above changes.
* spawn.cc (spawn_guts): Eliminate vestiges of "old way" of sending new hProc
to parent process.
This commit is contained in:
Christopher Faylor 2000-11-15 06:27:48 +00:00
parent fb0a875733
commit 84aeff4126
13 changed files with 144 additions and 119 deletions

View File

@ -1,3 +1,23 @@
Wed Nov 15 01:20:24 2000 Christopher Faylor <cgf@cygnus.com>
Throughout use myself->ppid_handle rather than parent_alive.
* child_info.h (child_info): Eliminate parent_alive.
* dcrt0.cc (dll_crt0_1): Call fork_init for debugging pid creation.
* fork.cc (fork_child): Reflect change to fixup_mmaps_after_fork
arguments.
(slow_pid_reuse): New function to grab last 'n' pids to prevent pid
reuse.
(fork_parent): Move last_fork_proc into slow_pid_reuse. Handle
fork_pids debugging. Eliminate unnecessary call to set_child_mmap_ptr.
(fork_init): New debugging function.
* mmap.cc (fixup_mmaps_after_fork): Renamed from
recreate_mmaps_after_fork. Rely on copied data after a fork.
(set_child_mmap_ptr): Eliminate.
* pinfo.h (_pinfo): Eliminate parent_alive, mmap_ptr and reflect above
changes.
* spawn.cc (spawn_guts): Eliminate vestiges of "old way" of sending new
hProc to parent process.
Wed Nov 15 0:51:00 2000 Corinna Vinschen <corinna@vinschen.de>
* cygheap.cc (cygheap_root::cygheap_root): New function.

View File

@ -36,7 +36,6 @@ public:
HANDLE subproc_ready; // used for synchronization with parent
HANDLE shared_h;
HANDLE console_h;
HANDLE parent_alive; // handle of thread used to track children
HANDLE parent;
HANDLE pppid_handle;
init_cygheap *cygheap;

View File

@ -56,7 +56,6 @@ BOOL display_title = FALSE;
BOOL strip_title_path = FALSE;
BOOL allow_glob = TRUE;
HANDLE NO_COPY parent_alive = NULL;
int cygwin_finished_initializing = 0;
/* Used in SIGTOMASK for generating a bit for insertion into a sigset_t.
@ -739,7 +738,6 @@ dll_crt0_1 ()
cygcwd.init ();
cygbench ("pre-forkee");
if (user_data->forkee)
{
/* If we've played with the stack, stacksize != 0. That means that
@ -758,6 +756,13 @@ dll_crt0_1 ()
longjmp (fork_info->jmp, fork_info->cygpid);
}
#ifdef DEBUGGING
{
extern void fork_init ();
fork_init ();
}
#endif
/* Initialize our process table entry. */
pinfo_init (envp, envc);
@ -910,16 +915,6 @@ _dll_crt0 ()
mypid = child_proc_info->cygpid;
cygwin_shared_h = child_proc_info->shared_h;
console_shared_h = child_proc_info->console_h;
/* We don't want subprocesses to inherit this */
if (dynamically_loaded)
parent_alive = NULL;
else if (!DuplicateHandle (hMainProc, child_proc_info->parent_alive,
hMainProc, &parent_alive, 0, 0,
DUPLICATE_SAME_ACCESS
| DUPLICATE_CLOSE_SOURCE))
system_printf ("parent_alive DuplicateHandle failed, %E");
break;
}
default:

View File

@ -92,7 +92,7 @@ stdio_init (void)
Also, always set them even if we're to pick up our parent's fds
in case they're missed. */
if (!parent_alive && NOTSTATE(myself, PID_CYGPARENT))
if (!myself->ppid_handle && NOTSTATE(myself, PID_CYGPARENT))
{
HANDLE in = GetStdHandle (STD_INPUT_HANDLE);
HANDLE out = GetStdHandle (STD_OUTPUT_HANDLE);

View File

@ -632,7 +632,7 @@ environ_init (char **envp, int envc)
char *eq;
if ((eq = strchr (newp, '=')) == NULL)
eq = strchr (newp, '\0');
if (!parent_alive)
if (!myself->ppid_handle)
ucenv (newp, eq);
if (*newp == 'T' && strncmp (newp, "TERM=", 5) == 0)
sawTERM = 1;

View File

@ -891,8 +891,8 @@ sig_handle_tty_stop (int sig)
pinfo parent (myself->ppid);
sig_send (parent, __SIGCHILDSTOPPED);
}
sigproc_printf ("process %d stopped by signal %d, parent_alive %p",
myself->pid, sig, parent_alive);
sigproc_printf ("process %d stopped by signal %d, myself->ppid_handle %p",
myself->pid, sig, myself->ppid_handle);
/* There is a small race here with the above two mutexes */
SuspendThread (hMainThread);
return;

View File

@ -29,6 +29,12 @@ details. */
#include "dll_init.h"
#include "security.h"
#ifdef DEBUGGING
static int npid = 0;
static int npid_max = 0;
static pid_t fork_pids[100] = {0};
#endif
DWORD NO_COPY chunksize = 0;
/* Timeout to wait for child to start, parent to init child, etc. */
/* FIXME: Once things stabilize, bump up to a few minutes. */
@ -289,7 +295,7 @@ fork_child (HANDLE& hParent, dll *&first_dll, bool& load_dlls)
(void) ForceCloseHandle (child_proc_info->subproc_ready);
(void) ForceCloseHandle (child_proc_info->forker_finished);
if (recreate_mmaps_after_fork (myself->mmap_ptr))
if (fixup_mmaps_after_fork ())
api_fatal ("recreate_mmaps_after_fork_failed");
/* Set thread local stuff to zero. Under Windows 95/98 this is sometimes
@ -305,17 +311,40 @@ fork_child (HANDLE& hParent, dll *&first_dll, bool& load_dlls)
return 0;
}
static void
slow_pid_reuse (HANDLE h)
{
static NO_COPY HANDLE last_fork_procs[64];
static NO_COPY unsigned nfork_procs = 0;
if (nfork_procs > (sizeof (last_fork_procs) / sizeof (last_fork_procs [0])))
nfork_procs = 0;
/* Keep a list of handles to forked processes sitting around to prevent
Windows from reusing the same pid n times in a row. Having the same pids
close in succesion confuses bash. Keeping a handle open will stop
windows from reusing the same pid. */
if (last_fork_procs[nfork_procs])
CloseHandle (last_fork_procs[nfork_procs]);
if (!DuplicateHandle (hMainProc, h, hMainProc, &last_fork_procs[nfork_procs],
0, FALSE, DUPLICATE_SAME_ACCESS))
{
last_fork_procs[nfork_procs] = NULL;
system_printf ("couldn't create last_fork_proc, %E");
}
nfork_procs++;
}
static int __stdcall
fork_parent (void *stack_here, HANDLE& hParent, dll *&first_dll, bool& load_dlls, child_info_fork &ch)
fork_parent (void *stack_here, HANDLE& hParent, dll *&first_dll,
bool& load_dlls, child_info_fork &ch)
{
HANDLE subproc_ready, forker_finished;
DWORD rc;
PROCESS_INFORMATION pi = {0, NULL, 0, 0};
static NO_COPY HANDLE last_fork_proc = NULL;
subproc_init ();
#ifdef DEBUGGING
#ifdef DEBUGGING_NOTNEEDED
/* The ProtectHandle call allocates memory so we need to make sure
that enough is set aside here so that the sbrk pointer does not
move when ProtectHandle is called after the child is started.
@ -348,6 +377,8 @@ fork_parent (void *stack_here, HANDLE& hParent, dll *&first_dll, bool& load_dlls
if (fdtab.need_fixup_before ())
c_flags |= CREATE_SUSPENDED;
/* Create an inheritable handle to pass to the child process. This will
allow the child to duplicate handles from the parent to itself. */
hParent = NULL;
if (!DuplicateHandle (hMainProc, hMainProc, hMainProc, &hParent, 0, 1,
DUPLICATE_SAME_ACCESS))
@ -407,6 +438,23 @@ fork_parent (void *stack_here, HANDLE& hParent, dll *&first_dll, bool& load_dlls
ch.parent = hParent;
ch.cygheap = cygheap;
ch.cygheap_max = cygheap_max;
#ifdef DEBUGGING
if (npid_max)
{
for (int pass = 0; pass < 2; pass++)
{
pid_t pid;
while ((pid = fork_pids[npid++]))
if (!pinfo (pid))
{
ch.cygpid = pid;
goto out;
}
npid = 0;
}
}
out:
#endif
char sa_buf[1024];
syscall_printf ("CreateProcess (%s, %s, 0, 0, 1, %x, 0, 0, %p, %p)",
@ -418,7 +466,7 @@ fork_parent (void *stack_here, HANDLE& hParent, dll *&first_dll, bool& load_dlls
TRUE, /* inherit handles from parent */
c_flags,
NULL, /* environment filled in later */
0, /* use current drive/directory */
0, /* use current drive/directory */
&si,
&pi);
@ -444,7 +492,11 @@ fork_parent (void *stack_here, HANDLE& hParent, dll *&first_dll, bool& load_dlls
ResumeThread (pi.hThread);
}
#ifdef DEBUGGING
pinfo forked ((ch.cygpid != 1 ? ch.cygpid : cygwin_pid (pi.dwProcessId)), 1);
#else
pinfo forked (cygwin_pid (pi.dwProcessId), 1);
#endif
/* Initialize things that are done later in dll_crt0_1 that aren't done
for the forkee. */
@ -459,22 +511,12 @@ fork_parent (void *stack_here, HANDLE& hParent, dll *&first_dll, bool& load_dlls
be called in subproc handling. */
ProtectHandle1 (pi.hProcess, childhProc);
/* Keep a handle to the current forked process sitting around to prevent
Windows from reusing the same pid twice in a row. Having the same pid
twice in a row confuses bash. So, after every CreateProcess, we can safely
remove the old pid and save a handle to the newly created process. Keeping
a handle open will stop windows from reusing the same pid. */
if (last_fork_proc)
CloseHandle (last_fork_proc);
if (!DuplicateHandle (hMainProc, pi.hProcess, hMainProc, &last_fork_proc,
0, FALSE, DUPLICATE_SAME_ACCESS))
system_printf ("couldn't create last_fork_proc, %E");
slow_pid_reuse (pi.hProcess);
/* Fill in fields in the child's process table entry. */
forked->hProcess = pi.hProcess;
forked->dwProcessId = pi.dwProcessId;
forked->copysigs(myself);
set_child_mmap_ptr (forked);
forked.remember ();
/* Wait for subproc to initialize itself. */
@ -602,6 +644,19 @@ fork ()
syscall_printf ("%d = fork()", res);
return res;
}
#ifdef DEBUGGING
void
fork_init ()
{
char buf[1024];
if (!GetEnvironmentVariable ("CYGWIN_FORK_PIDS", buf, 1024))
return;
pid_t pid;
char *p, *pe;
for (p = buf; (pid = strtol (p, &pe, 10)); p = pe)
fork_pids[npid_max++] = pid;
}
#endif /*DEBUGGING*/
#ifdef NEWVFORK
/* Dummy function to force second assignment below to actually be

View File

@ -156,7 +156,7 @@ map::erase (int i)
* needs to be specially handled by the fork code.
*/
static NO_COPY map *mmapped_areas;
static map *mmapped_areas;
extern "C"
caddr_t
@ -185,11 +185,11 @@ mmap (caddr_t addr, size_t len, int prot, int flags, int fd, off_t off)
}
#endif
if (mmapped_areas == 0)
if (mmapped_areas == NULL)
{
/* First mmap call, create STL map */
mmapped_areas = new map;
if (mmapped_areas == 0)
if (mmapped_areas == NULL)
{
set_errno (ENOMEM);
syscall_printf ("-1 = mmap(): ENOMEM");
@ -271,9 +271,9 @@ munmap (caddr_t addr, size_t len)
SetResourceLock(LOCK_MMAP_LIST,WRITE_LOCK|READ_LOCK," munmap");
/* Check if a mmap'ed area was ever created */
if (mmapped_areas == 0)
if (mmapped_areas == NULL)
{
syscall_printf ("-1 = munmap(): mmapped_areas == 0");
syscall_printf ("-1 = munmap(): mmapped_areas == NULL");
set_errno (EINVAL);
ReleaseResourceLock(LOCK_MMAP_LIST,WRITE_LOCK|READ_LOCK," munmap");
return -1;
@ -344,9 +344,9 @@ msync (caddr_t addr, size_t len, int flags)
SetResourceLock(LOCK_MMAP_LIST,WRITE_LOCK|READ_LOCK," msync");
/* Check if a mmap'ed area was ever created */
if (mmapped_areas == 0)
if (mmapped_areas == NULL)
{
syscall_printf ("-1 = msync(): mmapped_areas == 0");
syscall_printf ("-1 = msync(): mmapped_areas == NULL");
set_errno (EINVAL);
ReleaseResourceLock(LOCK_MMAP_LIST,WRITE_LOCK|READ_LOCK," msync");
return -1;
@ -549,31 +549,26 @@ mprotect (caddr_t addr, size_t len, int prot)
/*
* Call to re-create all the file mappings in a forked
* child. Called from the child in initialization. At this
* point we are passed a valid mmaped_areas map, and all the
* point we are passed a valid mmapped_areas map, and all the
* HANDLE's are valid for the child, but none of the
* mapped areas are in our address space. We need to iterate
* through the map, doing the MapViewOfFile calls.
*/
int __stdcall
recreate_mmaps_after_fork (void *param)
fixup_mmaps_after_fork ()
{
map *areas = (map *)param;
void *base;
debug_printf ("recreate_mmaps_after_fork, mmapped_areas %p", areas);
debug_printf ("recreate_mmaps_after_fork, mmapped_areas %p", mmapped_areas);
/* Check if a mmapped area was ever created */
if (areas == 0)
if (mmapped_areas == NULL)
return 0;
/* Iterate through the map */
int it;
for (it = 0; it < areas->nlists; ++it)
for (int it = 0; it < mmapped_areas->nlists; ++it)
{
list *l = areas->lists[it];
list *l = mmapped_areas->lists[it];
if (l != 0)
{
int li;
@ -586,34 +581,21 @@ recreate_mmaps_after_fork (void *param)
rec.get_size (), rec.get_address ());
/* Now re-create the MapViewOfFileEx call */
base = MapViewOfFileEx (rec.get_handle (),
rec.get_access (), 0,
rec.get_offset (),
rec.get_size (),
rec.get_address ());
void *base = MapViewOfFileEx (rec.get_handle (),
rec.get_access (), 0,
rec.get_offset (),
rec.get_size (),
rec.get_address ());
if (base != rec.get_address ())
{
system_printf ("base address %p fails to match requested address %p",
rec.get_address ());
return -1;
}
}
}
}
/* Now set our mmap record in case the child forks. */
mmapped_areas = areas;
}
}
}
debug_printf ("succeeded");
return 0;
}
/* Set a child mmap ptr from our static one. Used to set child mmap
pointer for fork. */
void __stdcall
set_child_mmap_ptr (_pinfo *child)
{
child->mmap_ptr = (void *) mmapped_areas;
}

View File

@ -59,8 +59,6 @@ public:
/* Used to spawn a child for fork(), among other things. */
char progname[MAX_PATH];
HANDLE parent_alive;
/* User information.
The information is derived from the GetUserName system call,
with the name looked up in /etc/passwd and assigned a default value
@ -83,8 +81,6 @@ public:
long start_time;
struct rusage rusage_self;
struct rusage rusage_children;
/* Pointer to mmap'ed areas for this process. Set up by fork. */
void *mmap_ptr;
/* Non-zero if process was stopped by a signal. */
char stopsig;
@ -209,8 +205,7 @@ extern void __stdcall pinfo_fixup_after_fork ();
extern HANDLE hexec_proc;
/* For mmaps across fork(). */
int __stdcall recreate_mmaps_after_fork (void *);
void __stdcall set_child_mmap_ptr (_pinfo *);
int __stdcall fixup_mmaps_after_fork ();
void __stdcall fill_rusage (struct rusage *, HANDLE);
void __stdcall add_rusage (struct rusage *, struct rusage *);

View File

@ -128,14 +128,14 @@ BOOL __stdcall
my_parent_is_alive ()
{
DWORD res;
if (!parent_alive)
if (!myself->ppid_handle)
{
debug_printf ("No parent_alive mutex");
debug_printf ("No myself->ppid_handle");
res = FALSE;
}
else
for (int i = 0; i < 2; i++)
switch (res = WaitForSingleObject (parent_alive, 0))
switch (res = WaitForSingleObject (myself->ppid_handle, 0))
{
case WAIT_OBJECT_0:
debug_printf ("parent dead.");
@ -149,8 +149,8 @@ my_parent_is_alive ()
DWORD werr = GetLastError ();
if (werr == ERROR_INVALID_HANDLE && i == 0)
continue;
system_printf ("WFSO for parent_alive(%p) failed, error %d",
parent_alive, werr);
system_printf ("WFSO for myself->ppid_handle(%p) failed, error %d",
myself->ppid_handle, werr);
res = FALSE;
goto out;
}
@ -304,6 +304,8 @@ proc_subproc (DWORD what, DWORD val)
hchildren[val] = hchildren[nchildren];
pchildren[val] = pchildren[nchildren];
}
/* Don't scan the wait queue yet. Caller will send SIGCHLD to this process.
This will cause an eventual scan of waiters. */
break;
/* A child is in the stopped state. Scan wait() queue to see if anyone
@ -816,7 +818,6 @@ subproc_init (void)
void __stdcall
init_child_info (DWORD chtype, child_info *ch, pid_t pid, HANDLE subproc_ready)
{
subproc_init ();
memset (ch, 0, sizeof *ch);
ch->cb = sizeof *ch;
ch->type = chtype;
@ -825,11 +826,6 @@ init_child_info (DWORD chtype, child_info *ch, pid_t pid, HANDLE subproc_ready)
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
DuplicateHandle (hMainProc, parent_alive, hMainProc, &ch->parent_alive,
0, 1, DUPLICATE_SAME_ACCESS);
}
/* Check the state of all of our children to see if any are stopped or

View File

@ -78,9 +78,6 @@ public:
extern sigthread mainthread;
extern HANDLE signal_arrived;
/* non-NULL if this process is a child of a cygwin process */
extern HANDLE parent_alive;
BOOL __stdcall my_parent_is_alive ();
extern "C" int __stdcall sig_dispatch_pending (int force = FALSE);
extern "C" void __stdcall set_process_mask (sigset_t newmask);

View File

@ -754,7 +754,7 @@ skip_arg_parsing:
if (mode == _P_OVERLAY)
{
res |= EXIT_REPARENTING;
if (!parent_alive)
if (!my_parent_is_alive ())
{
nwait = 1;
sigproc_terminate ();
@ -789,32 +789,19 @@ skip_arg_parsing:
* EXIT_REPARENTING status. Wait() syscall in parent will then wait
* for newly created child.
*/
pinfo parent (myself->ppid);
if (!parent)
/* nothing */;
else
HANDLE oldh = myself->hProcess;
HANDLE h = myself->ppid_handle;
sigproc_printf ("parent handle %p", h);
int 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);
if (!rc && my_parent_is_alive ())
{
int rc = 0;
HANDLE oldh = myself->hProcess;
HANDLE h = myself->ppid_handle;
sigproc_printf ("parent handle %p, pid %d", h, parent->dwProcessId);
if (h == NULL && GetLastError () == ERROR_INVALID_PARAMETER)
rc = 0;
else if (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);
}
if (!rc)
{
system_printf ("Reparent failed, parent handle %p, %E", h);
system_printf ("my dwProcessId %d, myself->dwProcessId %d",
GetCurrentProcessId(), myself->dwProcessId);
system_printf ("old hProcess %p, hProcess %p", oldh, myself->hProcess);
}
system_printf ("Reparent failed, parent handle %p, %E", h);
system_printf ("my dwProcessId %d, myself->dwProcessId %d",
GetCurrentProcessId(), myself->dwProcessId);
system_printf ("old hProcess %p, hProcess %p", oldh, myself->hProcess);
}
}

View File

@ -52,7 +52,6 @@ wait4 (int intpid, int *status, int options, struct rusage *r)
HANDLE waitfor;
sigframe thisframe (mainthread);
sigproc_printf ("here");
if (options & ~(WNOHANG | WUNTRACED))
{
set_errno (EINVAL);