* child_info.h: Bump magic number.

(class child_info): Add an element.
* cygheap.cc (init_cheap): Allocate cygwin heap in shared memory area.
(cygheap_fixup_in_child): Map cygwin heap, passed from parent via shared memory
into correct address.
(cygheap_setup_for_child): New function.
* cygheap.h: Declare new functions.
* dcrt0.cc (dll_crt0_1): Accomodate new cygheap_fixup_in_child arguments.
Avoid protecting subproc_ready unless it is spawn/nowait.
* fork.cc (fork_parent): Use new cygheap_setup_for_child function to setup
cygwin heap info.  Close passed cygheap shared memory handle.
* spawn.cc (spawn_guts): Ditto.  Also, reorganize to avoid synchronization
between parent and child in non-P_OVERLAY case.
* sigproc.cc (wait_sig): Only signal subproc_ready when execing.
This commit is contained in:
Christopher Faylor 2001-07-17 03:41:52 +00:00
parent 30640285c3
commit 5457dfcb81
9 changed files with 180 additions and 132 deletions

View File

@ -1,3 +1,20 @@
Mon 16 Jul 2001 10:47:17 PM EDT Christopher Faylor <cgf@cygnus.com>
* child_info.h: Bump magic number.
(class child_info): Add an element.
* cygheap.cc (init_cheap): Allocate cygwin heap in shared memory area.
(cygheap_fixup_in_child): Map cygwin heap, passed from parent via
shared memory into correct address.
(cygheap_setup_for_child): New function.
* cygheap.h: Declare new functions.
* dcrt0.cc (dll_crt0_1): Accomodate new cygheap_fixup_in_child
arguments. Avoid protecting subproc_ready unless it is spawn/nowait.
* fork.cc (fork_parent): Use new cygheap_setup_for_child function to
setup cygwin heap info. Close passed cygheap shared memory handle.
* spawn.cc (spawn_guts): Ditto. Also, reorganize to avoid
synchronization between parent and child in non-P_OVERLAY case.
* sigproc.cc (wait_sig): Only signal subproc_ready when execing.
Mon 16 Jul 2001 15:21:00 Corinna Vinschen <corinna@vinschen.de> Mon 16 Jul 2001 15:21:00 Corinna Vinschen <corinna@vinschen.de>
* grp.cc: Add missing Copyright date 2001. * grp.cc: Add missing Copyright date 2001.

View File

@ -12,7 +12,7 @@ details. */
enum enum
{ {
PROC_MAGIC = 0xaf0ff000, PROC_MAGIC = 0xaf10f000,
PROC_FORK = PROC_MAGIC + 1, PROC_FORK = PROC_MAGIC + 1,
PROC_EXEC = PROC_MAGIC + 2, PROC_EXEC = PROC_MAGIC + 2,
PROC_SPAWN = PROC_MAGIC + 3, PROC_SPAWN = PROC_MAGIC + 3,
@ -39,6 +39,7 @@ public:
HANDLE pppid_handle; HANDLE pppid_handle;
init_cygheap *cygheap; init_cygheap *cygheap;
void *cygheap_max; void *cygheap_max;
HANDLE cygheap_h;
}; };
class child_info_fork: public child_info class child_info_fork: public child_info

View File

@ -17,6 +17,7 @@
#include "fhandler.h" #include "fhandler.h"
#include "dtable.h" #include "dtable.h"
#include "cygheap.h" #include "cygheap.h"
#include "child_info.h"
#include "heap.h" #include "heap.h"
#include "cygerrno.h" #include "cygerrno.h"
#include "sync.h" #include "sync.h"
@ -28,15 +29,98 @@ void NO_COPY *cygheap_max = NULL;
static NO_COPY muto *cygheap_protect = NULL; static NO_COPY muto *cygheap_protect = NULL;
struct cygheap_entry
{
int type;
struct cygheap_entry *next;
char data[0];
};
#define NBUCKETS 32
char *buckets[NBUCKETS] = {0};
#define N0 ((_cmalloc_entry *) NULL)
#define to_cmalloc(s) ((_cmalloc_entry *) (((char *) (s)) - (int) (N0->data)))
extern "C" {
static void __stdcall _cfree (void *ptr) __attribute__((regparm(1)));
}
inline static void inline static void
init_cheap () init_cheap ()
{ {
cygheap = (init_cygheap *) VirtualAlloc (NULL, CYGHEAPSIZE, MEM_RESERVE, PAGE_NOACCESS); HANDLE cygheap_h;
cygheap_h = CreateFileMapping (INVALID_HANDLE_VALUE, &sec_none_nih,
PAGE_READWRITE | SEC_RESERVE, 0, CYGHEAPSIZE,
NULL);
cygheap = (init_cygheap *) MapViewOfFileEx (cygheap_h,
FILE_MAP_READ | FILE_MAP_WRITE,
0, 0, 0, NULL);
CloseHandle (cygheap_h);
if (!cygheap) if (!cygheap)
api_fatal ("Couldn't reserve space for cygwin's heap, %E"); api_fatal ("Couldn't reserve space for cygwin's heap, %E");
cygheap_max = cygheap + 1; cygheap_max = cygheap + 1;
} }
void __stdcall
cygheap_setup_for_child (child_info *ci)
{
void *newcygheap;
cygheap_protect->acquire ();
unsigned n = (char *) cygheap_max - (char *) cygheap;
ci->cygheap_h = CreateFileMapping (INVALID_HANDLE_VALUE, &sec_none,
PAGE_READWRITE | SEC_RESERVE, 0,
CYGHEAPSIZE, NULL);
newcygheap = MapViewOfFileEx (ci->cygheap_h, FILE_MAP_READ | FILE_MAP_WRITE,
0, 0, 0, NULL);
if (!VirtualAlloc (newcygheap, n, MEM_COMMIT, PAGE_READWRITE))
api_fatal ("couldn't allocate new heap for child, %E");
memcpy (newcygheap, cygheap, n);
UnmapViewOfFile (newcygheap);
ci->cygheap = cygheap;
ci->cygheap_max = cygheap_max;
ProtectHandle1 (ci->cygheap_h, passed_cygheap_h);
cygheap_protect->release ();
return;
}
/* Called by fork or spawn to reallocate cygwin heap */
void __stdcall
cygheap_fixup_in_child (child_info *ci, bool execed)
{
cygheap = ci->cygheap;
cygheap_max = ci->cygheap_max;
#if 0
if (!DuplicateHandle (hMainProc, ci->cygheap_h,
hMainProc, &cygheap_h, 0, 0,
DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE))
cygheap_h = ci->cygheap_h;
#endif
if (MapViewOfFileEx (ci->cygheap_h, FILE_MAP_READ | FILE_MAP_WRITE,
0, 0, 0, cygheap) != cygheap)
api_fatal ("Couldn't allocate space for child's heap from %p, to %p, %E",
cygheap, cygheap_max);
ForceCloseHandle1 (ci->cygheap_h, passed_cygheap_h);
cygheap_init ();
if (execed)
{
/* Walk the allocated memory chain looking for orphaned memory from
previous execs */
for (_cmalloc_entry *rvc = cygheap->chain; rvc; rvc = rvc->prev)
{
cygheap_entry *ce = (cygheap_entry *) rvc->data;
if (rvc->b >= NBUCKETS || ce->type <= HEAP_1_START)
continue;
else if (ce->type < HEAP_1_MAX)
ce->type += HEAP_1_MAX; /* Mark for freeing after next exec */
else
_cfree (ce); /* Marked by parent for freeing in child */
}
}
}
#define pagetrunc(x) ((void *) (((DWORD) (x)) & ~(4096 - 1))) #define pagetrunc(x) ((void *) (((DWORD) (x)) & ~(4096 - 1)))
static void *__stdcall static void *__stdcall
@ -76,12 +160,6 @@ cygheap_init ()
/* Copyright (C) 1997, 2000 DJ Delorie */ /* Copyright (C) 1997, 2000 DJ Delorie */
#define NBUCKETS 32
char *buckets[NBUCKETS] = {0};
#define N0 ((_cmalloc_entry *) NULL)
#define to_cmalloc(s) ((_cmalloc_entry *) (((char *) (s)) - (int) (N0->data)))
static void *_cmalloc (int size) __attribute ((regparm(1))); static void *_cmalloc (int size) __attribute ((regparm(1)));
static void *__stdcall _crealloc (void *ptr, int size) __attribute ((regparm(2))); static void *__stdcall _crealloc (void *ptr, int size) __attribute ((regparm(2)));
@ -115,7 +193,6 @@ _cmalloc (int size)
return rvc->data; return rvc->data;
} }
static void __stdcall _cfree (void *ptr) __attribute__((regparm(1)));
static void __stdcall static void __stdcall
_cfree (void *ptr) _cfree (void *ptr)
{ {
@ -150,57 +227,9 @@ _crealloc (void *ptr, int size)
#define sizeof_cygheap(n) ((n) + sizeof(cygheap_entry)) #define sizeof_cygheap(n) ((n) + sizeof(cygheap_entry))
struct cygheap_entry
{
int type;
struct cygheap_entry *next;
char data[0];
};
#define N ((cygheap_entry *) NULL) #define N ((cygheap_entry *) NULL)
#define tocygheap(s) ((cygheap_entry *) (((char *) (s)) - (int) (N->data))) #define tocygheap(s) ((cygheap_entry *) (((char *) (s)) - (int) (N->data)))
/* Called by fork or spawn to reallocate cygwin heap */
extern "C" void __stdcall
cygheap_fixup_in_child (HANDLE parent, bool execed)
{
DWORD m, n;
n = (DWORD) cygheap_max - (DWORD) cygheap;
/* Reserve cygwin heap in same spot as parent */
if (!VirtualAlloc (cygheap, CYGHEAPSIZE, MEM_RESERVE, PAGE_NOACCESS))
api_fatal ("Couldn't reserve space for cygwin's heap (%p) in child, cygheap, %E", cygheap);
/* Allocate same amount of memory as parent */
if (!VirtualAlloc (cygheap, n, MEM_COMMIT, PAGE_READWRITE))
api_fatal ("Couldn't allocate space for child's heap %p, size %d, %E",
cygheap, n);
/* Copy memory from the parent */
m = 0;
if (!ReadProcessMemory (parent, cygheap, cygheap, n, &m) || m != n)
api_fatal ("Couldn't read parent's cygwin heap %d bytes != %d, %E",
n, m);
cygheap_init ();
if (execed)
{
/* Walk the allocated memory chain looking for orphaned memory from
previous execs */
for (_cmalloc_entry *rvc = cygheap->chain; rvc; rvc = rvc->prev)
{
cygheap_entry *ce = (cygheap_entry *) rvc->data;
if (rvc->b >= NBUCKETS || ce->type <= HEAP_1_START)
continue;
else if (ce->type < HEAP_1_MAX)
ce->type += HEAP_1_MAX; /* Mark for freeing after next exec */
else
_cfree (ce); /* Marked by parent for freeing in child */
}
}
}
inline static void * inline static void *
creturn (cygheap_types x, cygheap_entry * c, int len) creturn (cygheap_types x, cygheap_entry * c, int len)
{ {

View File

@ -166,9 +166,11 @@ struct init_cygheap
extern init_cygheap *cygheap; extern init_cygheap *cygheap;
extern void *cygheap_max; extern void *cygheap_max;
class child_info;
void __stdcall cygheap_setup_for_child (child_info *ci) __attribute__ ((regparm(1)));
void __stdcall cygheap_fixup_in_child (child_info *, bool);
extern "C" { extern "C" {
void __stdcall cfree (void *) __attribute__ ((regparm(1))); void __stdcall cfree (void *) __attribute__ ((regparm(1)));
void __stdcall cygheap_fixup_in_child (HANDLE, bool);
void *__stdcall cmalloc (cygheap_types, DWORD) __attribute__ ((regparm(2))); void *__stdcall cmalloc (cygheap_types, DWORD) __attribute__ ((regparm(2)));
void *__stdcall crealloc (void *, DWORD) __attribute__ ((regparm(2))); void *__stdcall crealloc (void *, DWORD) __attribute__ ((regparm(2)));
void *__stdcall ccalloc (cygheap_types, DWORD, DWORD) __attribute__ ((regparm(3))); void *__stdcall ccalloc (cygheap_types, DWORD, DWORD) __attribute__ ((regparm(3)));

View File

@ -669,13 +669,11 @@ dll_crt0_1 ()
if (child_proc_info) if (child_proc_info)
{ {
cygheap = child_proc_info->cygheap;
cygheap_max = child_proc_info->cygheap_max;
switch (child_proc_info->type) switch (child_proc_info->type)
{ {
case PROC_FORK: case PROC_FORK:
case PROC_FORK1: case PROC_FORK1:
cygheap_fixup_in_child (child_proc_info->parent, 0); cygheap_fixup_in_child (child_proc_info, 0);
alloc_stack (fork_info); alloc_stack (fork_info);
set_myself (mypid); set_myself (mypid);
user_data->heaptop = child_proc_info->heaptop; user_data->heaptop = child_proc_info->heaptop;
@ -690,7 +688,7 @@ dll_crt0_1 ()
hexec_proc = spawn_info->hexec_proc; hexec_proc = spawn_info->hexec_proc;
around: around:
HANDLE h; HANDLE h;
cygheap_fixup_in_child (spawn_info->parent, 1); cygheap_fixup_in_child (spawn_info, 1);
if (!spawn_info->moreinfo->myself_pinfo || if (!spawn_info->moreinfo->myself_pinfo ||
!DuplicateHandle (hMainProc, spawn_info->moreinfo->myself_pinfo, !DuplicateHandle (hMainProc, spawn_info->moreinfo->myself_pinfo,
hMainProc, &h, 0, 0, hMainProc, &h, 0, 0,
@ -709,7 +707,8 @@ dll_crt0_1 ()
old_title = strcpy (title_buf, spawn_info->moreinfo->old_title); old_title = strcpy (title_buf, spawn_info->moreinfo->old_title);
cfree (spawn_info->moreinfo->old_title); cfree (spawn_info->moreinfo->old_title);
} }
ProtectHandle (child_proc_info->subproc_ready); if (child_proc_info->subproc_ready)
ProtectHandle (child_proc_info->subproc_ready);
myself->uid = spawn_info->moreinfo->uid; myself->uid = spawn_info->moreinfo->uid;
if (myself->uid == USHRT_MAX) if (myself->uid == USHRT_MAX)
cygheap->user.set_sid (NULL); cygheap->user.set_sid (NULL);

View File

@ -442,8 +442,7 @@ fork_parent (HANDLE& hParent, dll *&first_dll,
RevertToSelf (); RevertToSelf ();
ch.parent = hParent; ch.parent = hParent;
ch.cygheap = cygheap; cygheap_setup_for_child (&ch);
ch.cygheap_max = cygheap_max;
#ifdef DEBUGGING #ifdef DEBUGGING
if (npid_max) if (npid_max)
{ {
@ -477,6 +476,7 @@ out:
&pi); &pi);
CloseHandle (hParent); CloseHandle (hParent);
ForceCloseHandle1 (ch.cygheap_h, passed_cygheap_h);
if (!rc) if (!rc)
{ {

View File

@ -86,7 +86,7 @@ open_shared (const char *name, HANDLE &shared_h, DWORD size, void *addr)
/* Probably win95, so try without specifying the address. */ /* Probably win95, so try without specifying the address. */
shared = (shared_info *) MapViewOfFileEx (shared_h, shared = (shared_info *) MapViewOfFileEx (shared_h,
FILE_MAP_READ|FILE_MAP_WRITE, FILE_MAP_READ|FILE_MAP_WRITE,
0,0,0,0); 0, 0, 0, 0);
} }
if (!shared) if (!shared)

View File

@ -1103,8 +1103,7 @@ wait_sig (VOID *)
* windows process waiting to see if it's started a cygwin process or not. * windows process waiting to see if it's started a cygwin process or not.
* Signalling subproc_ready indicates that we are a cygwin process. * Signalling subproc_ready indicates that we are a cygwin process.
*/ */
if (child_proc_info && if (child_proc_info && child_proc_info->type == PROC_EXEC)
(child_proc_info->type == PROC_EXEC || child_proc_info->type == PROC_SPAWN))
{ {
debug_printf ("subproc_ready %p", child_proc_info->subproc_ready); debug_printf ("subproc_ready %p", child_proc_info->subproc_ready);
if (!SetEvent (child_proc_info->subproc_ready)) if (!SetEvent (child_proc_info->subproc_ready))

View File

@ -327,8 +327,14 @@ spawn_guts (HANDLE hToken, const char * prog_arg, const char *const *argv,
else else
chtype = PROC_EXEC; chtype = PROC_EXEC;
HANDLE spr = CreateEvent (&sec_all, TRUE, FALSE, NULL); HANDLE spr;
ProtectHandle (spr); if (mode != _P_OVERLAY)
spr = NULL;
else
{
spr = CreateEvent (&sec_all, TRUE, FALSE, NULL);
ProtectHandle (spr);
}
init_child_info (chtype, &ciresrv, (mode == _P_OVERLAY) ? myself->pid : 1, spr); init_child_info (chtype, &ciresrv, (mode == _P_OVERLAY) ? myself->pid : 1, spr);
if (!DuplicateHandle (hMainProc, hMainProc, hMainProc, &ciresrv.parent, 0, 1, if (!DuplicateHandle (hMainProc, hMainProc, hMainProc, &ciresrv.parent, 0, 1,
@ -572,8 +578,7 @@ skip_arg_parsing:
else else
envblock = winenv (envp, 0); envblock = winenv (envp, 0);
ciresrv.cygheap = cygheap; cygheap_setup_for_child (&ciresrv);
ciresrv.cygheap_max = cygheap_max;
/* Preallocated buffer for `sec_user' call */ /* Preallocated buffer for `sec_user' call */
char sa_buf[1024]; char sa_buf[1024];
@ -669,6 +674,7 @@ skip_arg_parsing:
MALLOC_CHECK; MALLOC_CHECK;
if (envblock) if (envblock)
free (envblock); free (envblock);
ForceCloseHandle1 (ciresrv.cygheap_h, passed_cygheap_h);
MALLOC_CHECK; MALLOC_CHECK;
/* Set errno now so that debugging messages from it appear before our /* Set errno now so that debugging messages from it appear before our
@ -741,88 +747,83 @@ skip_arg_parsing:
DWORD res; DWORD res;
BOOL exited; BOOL exited;
HANDLE waitbuf[3] = {pi.hProcess, signal_arrived, spr};
int nwait = 3;
bool saw_signal = 0;
res = 0; res = 0;
exited = FALSE; exited = FALSE;
MALLOC_CHECK; MALLOC_CHECK;
for (int i = 0; i < 100; i++) if (mode == _P_OVERLAY)
{ {
switch (WaitForMultipleObjects (nwait, waitbuf, FALSE, INFINITE)) int nwait = 3;
HANDLE waitbuf[3] = {pi.hProcess, signal_arrived, spr};
for (int i = 0; i < 100; i++)
{ {
case WAIT_OBJECT_0: switch (WaitForMultipleObjects (nwait, waitbuf, FALSE, INFINITE))
sigproc_printf ("subprocess exited");
DWORD exitcode;
if (!GetExitCodeProcess (pi.hProcess, &exitcode))
exitcode = 1;
res |= exitcode;
exited = TRUE;
break;
case WAIT_OBJECT_0 + 1:
sigproc_printf ("signal arrived");
reset_signal_arrived ();
saw_signal = 1;
continue;
case WAIT_OBJECT_0 + 2:
if (mode == _P_OVERLAY)
{ {
case WAIT_OBJECT_0:
sigproc_printf ("subprocess exited");
DWORD exitcode;
if (!GetExitCodeProcess (pi.hProcess, &exitcode))
exitcode = 1;
res |= exitcode;
exited = TRUE;
break;
case WAIT_OBJECT_0 + 1:
sigproc_printf ("signal arrived");
reset_signal_arrived ();
continue;
case WAIT_OBJECT_0 + 2:
if (myself->ppid_handle) if (myself->ppid_handle)
res |= EXIT_REPARENTING; res |= EXIT_REPARENTING;
if (!my_parent_is_alive ()) if (!my_parent_is_alive ())
{ {
nwait = 1; nwait = 2;
sigproc_terminate (); sigproc_terminate ();
continue; continue;
} }
break;
case WAIT_FAILED:
system_printf ("wait failed: nwait %d, pid %d, winpid %d, %E",
nwait, myself->pid, myself->dwProcessId);
system_printf ("waitbuf[0] %p %d", waitbuf[0],
WaitForSingleObject (waitbuf[0], 0));
system_printf ("waitbuf[1] %p = %d", waitbuf[1],
WaitForSingleObject (waitbuf[1], 0));
system_printf ("waitbuf[w] %p = %d", waitbuf[2],
WaitForSingleObject (waitbuf[2], 0));
set_errno (ECHILD);
try_to_debug ();
return -1;
} }
break; break;
case WAIT_FAILED:
system_printf ("wait failed: nwait %d, pid %d, winpid %d, %E",
nwait, myself->pid, myself->dwProcessId);
system_printf ("waitbuf[0] %p %d", waitbuf[0],
WaitForSingleObject (waitbuf[0], 0));
system_printf ("waitbuf[1] %p = %d", waitbuf[1],
WaitForSingleObject (waitbuf[1], 0));
system_printf ("waitbuf[w] %p = %d", waitbuf[2],
WaitForSingleObject (waitbuf[2], 0));
set_errno (ECHILD);
try_to_debug ();
return -1;
} }
break;
}
ForceCloseHandle (spr); ForceCloseHandle (spr);
sigproc_printf ("res = %x", res); sigproc_printf ("res = %x", res);
if (mode == _P_OVERLAY && (res & EXIT_REPARENTING)) if (res & EXIT_REPARENTING)
{
/* Try to reparent child process.
* Make handles to child available to parent process and exit with
* EXIT_REPARENTING status. Wait() syscall in parent will then wait
* for newly created child.
*/
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 ())
{ {
system_printf ("Reparent failed, parent handle %p, %E", h); /* Try to reparent child process.
system_printf ("my dwProcessId %d, myself->dwProcessId %d", * Make handles to child available to parent process and exit with
GetCurrentProcessId (), myself->dwProcessId); * EXIT_REPARENTING status. Wait() syscall in parent will then wait
system_printf ("old hProcess %p, hProcess %p", oldh, myself->hProcess); * for newly created child.
*/
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 ())
{
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);
}
} }
}
if (saw_signal && mode != _P_OVERLAY) }
thisframe.call_signal_handler ();
MALLOC_CHECK; MALLOC_CHECK;