* child_info.h (child_info::cygheap_h): Delete.

(child_info::dwProcessId): New field.
* cygheap.cc (init_cheap): Delete.
(dup_now): Ditto.
(cygheap_setup_for_child): Ditto.
(cygheap_setup_for_child_cleanup): Ditto.
(cygheap_fixup_in_child): Simplify.  Use new "child_copy" function to copy heap
from parent.
(_csbrk): Don't attempt allocation if within cygheap section.  Fix so that more
than one allocation will succeed.
(cygheap_init): Reset possibly-nonzero region to zero.
* cygheap.h (cygheap_setup_for_child): Delete declaration.
(cygheap_setup_for_child_cleanup): Ditto.
(cygheap_start): Define as an array.
* cygwin.sc: Modernize.  Remove unneeded sections.  Define cygheap here.
* dcrt0.cc (do_exit): Reflect argument change to close_all_files.
* dtable.cc (dtable::vfork_parent_restore): Ditto.
* dtable.h: Ditto.
* fhandler.h: Ditto.
* fork.cc (fork_copy): Call ReadProcessMemory if there is no thread
(indicating that we're execing).
(fork_child): Don't mess with hParent.
(fork_parent): Remove hParent stuff.  It happens earlier now.  Remove call to
cygheap_setup_for_child* stuff.
(fork): Put child_info_stuff in grouped structure.  Issue error if parent
handle is not set.
(child_copy): New function.
* sigproc.cc (child_info::child_info): Put cygheap settings here.  Set parent
handle.
(child_info::~child_info): Close parent handle if it exists.
* spawn.cc (spawn_guts): Reorganize so that ciresrv is allocated at only the
last minute so that cygheap changes are reflected.  Delete cygheap_setup*
calls.
* syscalls.cc (close_all_files): Add an argument to flag when the fd entry
should be released.
* winsup.h (close_all_files): Add an argument to close_all_files declaration.
Declare child_copy.
This commit is contained in:
Christopher Faylor 2005-06-01 03:46:56 +00:00
parent 302cb8165e
commit ce95c6407e
14 changed files with 202 additions and 280 deletions

View File

@ -1,3 +1,44 @@
2005-05-30 Christopher Faylor <cgf@timesys.com>
* child_info.h (child_info::cygheap_h): Delete.
(child_info::dwProcessId): New field.
* cygheap.cc (init_cheap): Delete.
(dup_now): Ditto.
(cygheap_setup_for_child): Ditto.
(cygheap_setup_for_child_cleanup): Ditto.
(cygheap_fixup_in_child): Simplify. Use new "child_copy" function to
copy heap from parent.
(_csbrk): Don't attempt allocation if within cygheap section. Fix so
that more than one allocation will succeed.
(cygheap_init): Reset possibly-nonzero region to zero.
* cygheap.h (cygheap_setup_for_child): Delete declaration.
(cygheap_setup_for_child_cleanup): Ditto.
(cygheap_start): Define as an array.
* cygwin.sc: Modernize. Remove unneeded sections. Define cygheap
here.
* dcrt0.cc (do_exit): Reflect argument change to close_all_files.
* dtable.cc (dtable::vfork_parent_restore): Ditto.
* dtable.h: Ditto.
* fhandler.h: Ditto.
* fork.cc (fork_copy): Call ReadProcessMemory if there is no thread
(indicating that we're execing).
(fork_child): Don't mess with hParent.
(fork_parent): Remove hParent stuff. It happens earlier now.
Remove call to cygheap_setup_for_child* stuff.
(fork): Put child_info_stuff in grouped structure. Issue error if
parent handle is not set.
(child_copy): New function.
* sigproc.cc (child_info::child_info): Put cygheap settings here. Set
parent handle.
(child_info::~child_info): Close parent handle if it exists.
* spawn.cc (spawn_guts): Reorganize so that ciresrv is allocated at
only the last minute so that cygheap changes are reflected. Delete
cygheap_setup* calls.
* syscalls.cc (close_all_files): Add an argument to flag when the fd
entry should be released.
* winsup.h (close_all_files): Add an argument to close_all_files
declaration. Declare child_copy.
2005-05-30 Vaclav Haisman <v.haisman@sh.cvut.cz>
* thread.h (List_remove): Make node parameter const. Use simple

View File

@ -29,7 +29,7 @@ enum child_info_types
#define EXEC_MAGIC_SIZE sizeof(child_info)
#define CURR_CHILD_INFO_MAGIC 0xd079e02U
#define CURR_CHILD_INFO_MAGIC 0xd94c588aU
/* NOTE: Do not make gratuitous changes to the names or organization of the
below class. The layout is checksummed to determine compatibility between
@ -48,7 +48,7 @@ public:
init_cygheap *cygheap;
void *cygheap_max;
DWORD cygheap_reserve_sz;
HANDLE cygheap_h;
DWORD dwProcessId;
unsigned fhandler_union_cb;
child_info (unsigned, child_info_types);
~child_info ();

View File

@ -22,12 +22,16 @@
#include "heap.h"
#include "sync.h"
#include "sigproc.h"
#include "pinfo.h"
#include <unistd.h>
init_cygheap NO_COPY *cygheap;
void NO_COPY *cygheap_max;
extern "C" char _cygheap_mid[] __attribute__((section(".cygheap")));
extern "C" char _cygheap_end[] __attribute__((section(".cygheap_end")));
static NO_COPY muto cygheap_protect;
static NO_COPY DWORD reserve_sz;
struct cygheap_entry
{
@ -44,141 +48,20 @@ struct cygheap_entry
#define MVMAP_OPTIONS (FILE_MAP_WRITE)
extern "C" {
static void __stdcall _cfree (void *ptr) __attribute__((regparm(1)));
}
static void
init_cheap ()
{
#ifndef DEBUGGING
reserve_sz = CYGHEAPSIZE;
#else
char buf[80];
DWORD initial_sz = 0;
if (!GetEnvironmentVariable ("CYGWIN_HEAPSIZE", buf, sizeof buf - 1))
initial_sz = reserve_sz = CYGHEAPSIZE;
else
{
initial_sz = reserve_sz = atoi (buf);
small_printf ("using cygheap size %d\n", reserve_sz);
}
#endif
do
if ((cygheap = (init_cygheap *) VirtualAlloc ((void *) &_cygheap_start,
reserve_sz, MEM_RESERVE,
PAGE_NOACCESS)))
break;
while ((reserve_sz -= 2 * (1024 * 1024)) >= CYGHEAPSIZE_MIN);
#ifdef DEBUGGING
if (reserve_sz != initial_sz)
small_printf ("reset initial cygheap size to %u\n", reserve_sz);
#endif
if (!cygheap)
{
MEMORY_BASIC_INFORMATION m;
if (!VirtualQuery ((LPCVOID) &_cygheap_start, &m, sizeof m))
system_printf ("couldn't get memory info, %E");
system_printf ("Couldn't reserve %d bytes of space for cygwin's heap, %E",
reserve_sz);
api_fatal ("AllocationBase %p, BaseAddress %p, RegionSize %p, State %p\n",
m.AllocationBase, m.BaseAddress, m.RegionSize, m.State);
}
cygheap_max = cygheap;
}
static void dup_now (void *, child_info *, unsigned) __attribute__ ((regparm(3)));
static void
dup_now (void *newcygheap, child_info *ci, unsigned n)
{
if (!VirtualAlloc (newcygheap, n, MEM_COMMIT, PAGE_READWRITE))
api_fatal ("couldn't allocate new cygwin heap %p, %d for child, %E",
newcygheap, n);
memcpy (newcygheap, cygheap, n);
}
void *__stdcall
cygheap_setup_for_child (child_info *ci, bool dup_later)
{
void *newcygheap;
cygheap_protect.acquire ();
unsigned n = (char *) cygheap_max - (char *) cygheap;
unsigned size = reserve_sz;
if (size < n)
size = n + (128 * 1024);
ci->cygheap_h = CreateFileMapping (INVALID_HANDLE_VALUE, &sec_none,
CFMAP_OPTIONS, 0, size, NULL);
if (!ci->cygheap_h)
api_fatal ("Couldn't create heap for child, size %d, %E", size);
newcygheap = MapViewOfFileEx (ci->cygheap_h, MVMAP_OPTIONS, 0, 0, 0, NULL);
if (!newcygheap)
api_fatal ("couldn't map space for new cygheap, %E");
ProtectHandle1INH (ci->cygheap_h, passed_cygheap_h);
if (!dup_later)
dup_now (newcygheap, ci, n);
cygheap_protect.release ();
ci->cygheap = cygheap;
ci->cygheap_max = cygheap_max;
ci->cygheap_reserve_sz = size;
return newcygheap;
}
void __stdcall
cygheap_setup_for_child_cleanup (void *newcygheap, child_info *ci,
bool dup_it_now)
{
if (dup_it_now)
{
/* NOTE: There is an assumption here that cygheap_max has not changed
between the time that cygheap_setup_for_child was called and now.
Make sure that this is a correct assumption. */
cygheap_protect.acquire ();
dup_now (newcygheap, ci, (char *) cygheap_max - (char *) cygheap);
cygheap_protect.release ();
}
UnmapViewOfFile (newcygheap);
ForceCloseHandle1 (ci->cygheap_h, passed_cygheap_h);
static void __stdcall _cfree (void *) __attribute__((regparm(1)));
static void *__stdcall _csbrk (int);
}
/* Called by fork or spawn to reallocate cygwin heap */
void __stdcall
cygheap_fixup_in_child (bool execed)
{
cygheap = child_proc_info->cygheap;
cygheap_max = child_proc_info->cygheap_max;
void *addr = !wincap.map_view_of_file_ex_sucks () ? cygheap : NULL;
void *newaddr;
newaddr = MapViewOfFileEx (child_proc_info->cygheap_h, MVMAP_OPTIONS, 0, 0, 0, addr);
reserve_sz = child_proc_info->cygheap_reserve_sz;
if (newaddr != cygheap)
{
if (!newaddr)
newaddr = MapViewOfFileEx (child_proc_info->cygheap_h, MVMAP_OPTIONS, 0, 0, 0, NULL);
DWORD n = (DWORD) cygheap_max - (DWORD) cygheap;
/* Reserve cygwin heap in same spot as parent */
if (!VirtualAlloc (cygheap, reserve_sz, MEM_RESERVE, PAGE_NOACCESS))
{
MEMORY_BASIC_INFORMATION m;
memset (&m, 0, sizeof m);
if (!VirtualQuery ((LPCVOID) cygheap, &m, sizeof m))
system_printf ("couldn't get memory info, %E");
system_printf ("Couldn't reserve %d bytes of space for cygwin's heap (%p <%p>) in child, %E",
reserve_sz, cygheap, newaddr);
api_fatal ("m.AllocationBase %p, m.BaseAddress %p, m.RegionSize %p, m.State %p\n",
m.AllocationBase, m.BaseAddress, m.RegionSize, m.State);
}
/* 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);
memcpy (cygheap, newaddr, n);
UnmapViewOfFile (newaddr);
}
ForceCloseHandle1 (child_proc_info->cygheap_h, passed_cygheap_h);
cygheap_max = child_proc_info->cygheap;
cygheap = (init_cygheap *) cygheap_max;
_csbrk ((char *) child_proc_info->cygheap_max - (char *) cygheap);
child_copy (child_proc_info->parent, child_proc_info->dwProcessId, "cygheap", cygheap, cygheap_max);
if (execed)
CloseHandle (child_proc_info->parent);
cygheap_init ();
debug_fixup_after_fork_exec ();
@ -222,31 +105,43 @@ init_cygheap::close_ctty ()
#endif
}
#define pagetrunc(x) ((void *) (((DWORD) (x)) & ~(4096 - 1)))
#define nextpage(x) ((char *) (((DWORD) ((char *) x + granmask)) & ~granmask))
#define allocsize(x) ((DWORD) nextpage (x))
#ifdef DEBUGGING
#define somekinda_printf debug_printf
#else
#define somekinda_printf malloc_printf
#endif
static void *__stdcall
_csbrk (int sbs)
{
void *prebrk = cygheap_max;
void *prebrka = pagetrunc (prebrk);
size_t granmask = getshmlba () - 1;
char *newbase = nextpage (prebrk);
cygheap_max = (char *) cygheap_max + sbs;
if (!sbs || (prebrk != prebrka && prebrka == pagetrunc (cygheap_max)))
if (!sbs || (newbase > cygheap_max) || (cygheap_max < _cygheap_end))
/* nothing to do */;
else if (!VirtualAlloc (prebrk, (DWORD) sbs, MEM_COMMIT, PAGE_READWRITE))
else
{
#ifdef DEBUGGING
system_printf ("couldn't commit memory for cygwin heap, prebrk %p, size %d, heapsize now %d, max heap size %u, %E",
prebrk, sbs, (char *) cygheap_max - (char *) cygheap,
reserve_sz);
#else
malloc_printf ("couldn't commit memory for cygwin heap, prebrk %p, size %d, heapsize now %d, max heap size %u, %E",
prebrk, sbs, (char *) cygheap_max - (char *) cygheap,
reserve_sz);
#endif
if (prebrk <= _cygheap_end)
newbase = _cygheap_end;
DWORD adjsbs = allocsize ((char *) cygheap_max - newbase);
if (!VirtualAlloc (newbase, adjsbs, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE))
{
MEMORY_BASIC_INFORMATION m;
if (!VirtualQuery (newbase, &m, sizeof m))
system_printf ("couldn't get memory info, %E");
somekinda_printf ("Couldn't reserve/commit %d bytes of space for cygwin's heap, %E",
adjsbs);
somekinda_printf ("AllocationBase %p, BaseAddress %p, RegionSize %p, State %p\n",
m.AllocationBase, m.BaseAddress, m.RegionSize, m.State);
__seterrno ();
cygheap_max = (char *) cygheap_max - sbs;
return NULL;
}
}
return prebrk;
}
@ -257,7 +152,13 @@ cygheap_init ()
cygheap_protect.init ("cygheap_protect");
if (!cygheap)
{
init_cheap ();
#if 1
cygheap = (init_cygheap *) memset (_cygheap_start, 0, _cygheap_mid - _cygheap_start);
#else
cygheap = (init_cygheap *) _cygheap_start;
#endif
cygheap_max = cygheap;
(void) _csbrk (sizeof (*cygheap));
}
if (!cygheap->fdtab)

View File

@ -416,8 +416,6 @@ class cygheap_fdenum : public cygheap_fdmanip
};
class child_info;
void *__stdcall cygheap_setup_for_child (child_info *ci, bool dup_later) __attribute__ ((regparm(2)));
void __stdcall cygheap_setup_for_child_cleanup (void *, child_info *, bool) __attribute__ ((regparm(3)));
void __stdcall cygheap_fixup_in_child (bool);
extern "C" {
void __stdcall cfree (void *) __attribute__ ((regparm(1)));
@ -428,5 +426,5 @@ char *__stdcall cstrdup (const char *) __attribute__ ((regparm(1)));
char *__stdcall cstrdup1 (const char *) __attribute__ ((regparm(1)));
void __stdcall cfree_and_set (char *&, char * = NULL) __attribute__ ((regparm(2)));
void __stdcall cygheap_init ();
extern DWORD _cygheap_start __attribute__((section(".cygheap")));
extern char _cygheap_start[] __attribute__((section(".idata")));
}

View File

@ -1,6 +1,4 @@
OUTPUT_FORMAT(pei-i386)
SEARCH_DIR(/cygnus/i686-pc-cygwin/lib/w32api); SEARCH_DIR(/cygnus/i686-pc-cygwin/lib);
ENTRY(_mainCRTStartup)
SECTIONS
{
.text __image_base__ + __section_alignment__ :
@ -10,9 +8,9 @@ SECTIONS
*(SORT(.text$*))
*(.glue_7t)
*(.glue_7)
___CTOR_LIST__ = .; __CTOR_LIST__ = . ;
___CTOR_LIST__ = .; __CTOR_LIST__ = .;
LONG (-1); *(SORT(.ctors.*)); *(.ctors); *(.ctor); LONG (0);
___DTOR_LIST__ = .; __DTOR_LIST__ = . ;
___DTOR_LIST__ = .; __DTOR_LIST__ = .;
LONG (-1); *(SORT(.dtors.*)); *(.dtors); *(.dtor); LONG (0);
*(.fini)
/* ??? Why is .gcc_exc here? */
@ -20,38 +18,42 @@ SECTIONS
etext = .;
*(.gcc_except_table)
}
.autoload_text ALIGN(__section_alignment__) :
{
*(.*_text);
}
/* The Cygwin DLL uses a section to avoid copying certain data
on fork. This used to be named ".data". The linker used
to include this between __data_start__ and __data_end__, but that
breaks building the cygwin32 dll. Instead, we name the section
".data_cygwin_nocopy" and explictly include it after __data_end__. */
.data BLOCK(__section_alignment__) :
.data ALIGN(__section_alignment__) :
{
__data_start__ = . ;
__data_start__ = .;
*(.data)
*(.data2)
*(SORT(.data$*))
__data_end__ = . ;
__data_end__ = .;
*(.data_cygwin_nocopy)
}
.rdata BLOCK(__section_alignment__) :
.rdata ALIGN(__section_alignment__) :
{
*(.rdata)
*(SORT(.rdata$*))
*(.eh_frame)
}
.pdata BLOCK(__section_alignment__) :
.pdata ALIGN(__section_alignment__) :
{
*(.pdata)
}
.bss BLOCK(__section_alignment__) :
.bss ALIGN(__section_alignment__) :
{
__bss_start__ = . ;
__bss_start__ = .;
*(.bss)
*(COMMON)
__bss_end__ = . ;
__bss_end__ = .;
}
.edata BLOCK(__section_alignment__) :
.edata ALIGN(__section_alignment__) :
{
*(.edata)
}
@ -62,7 +64,28 @@ SECTIONS
*(.debug$F)
*(.drectve)
}
.idata BLOCK(__section_alignment__) :
.stab ALIGN(__section_alignment__) (NOLOAD) :
{
[ .stab ]
}
.stabstr ALIGN(__section_alignment__) (NOLOAD) :
{
[ .stabstr ]
}
/* DWARF 1.1 and DWARF 2 */
.debug_aranges ALIGN(__section_alignment__) (NOLOAD) : { *(.debug_aranges) }
.debug_pubnames ALIGN(__section_alignment__) (NOLOAD) : { *(.debug_pubnames) }
/* DWARF 2 */
.debug_info ALIGN(__section_alignment__) (NOLOAD) : { *(.debug_info) }
.debug_abbrev ALIGN(__section_alignment__) (NOLOAD) : { *(.debug_abbrev) }
.debug_line ALIGN(__section_alignment__) (NOLOAD) : { *(.debug_line) }
.debug_frame ALIGN(__section_alignment__) (NOLOAD) : { *(.debug_frame) }
.debug_str ALIGN(__section_alignment__) (NOLOAD) : { *(.debug_str) }
.debug_loc ALIGN(__section_alignment__) (NOLOAD) : { *(.debug_loc) }
.debug_macinfo ALIGN(__section_alignment__) (NOLOAD) : { *(.debug_macinfo) }
.debug_macinfo ALIGN(__section_alignment__) (NOLOAD) : { *(.debug_macinfo) }
.debug_ranges ALIGN(__section_alignment__) (NOLOAD) : { *(.debug_ranges) }
.idata ALIGN(__section_alignment__) :
{
/* This cannot currently be handled with grouped sections.
See pe.em:sort_sections. */
@ -74,51 +97,17 @@ SECTIONS
SORT(*)(.idata$5)
SORT(*)(.idata$6)
SORT(*)(.idata$7)
. = ALIGN(16);
__cygheap_start = ABSOLUTE(.);
}
.CRT BLOCK(__section_alignment__) :
osection_alignment = __section_alignment__;
__section_alignment__ = 64 * 1024;
.cygheap ALIGN(4096):
{
*(SORT(.CRT$*))
}
.endjunk BLOCK(__section_alignment__) :
{
/* end is deprecated, don't use it */
end = .;
_end = .;
__end__ = .;
}
.rsrc BLOCK(__section_alignment__) :
{
*(.rsrc)
*(SORT(.rsrc$*))
}
.reloc BLOCK(__section_alignment__) :
{
*(.reloc)
}
.stab BLOCK(__section_alignment__) (NOLOAD) :
{
[ .stab ]
}
.stabstr BLOCK(__section_alignment__) (NOLOAD) :
{
[ .stabstr ]
}
/* DWARF 1.1 and DWARF 2 */
.debug_aranges BLOCK(__section_alignment__) (NOLOAD) : { *(.debug_aranges) }
.debug_pubnames BLOCK(__section_alignment__) (NOLOAD) : { *(.debug_pubnames) }
/* DWARF 2 */
.debug_info BLOCK(__section_alignment__) (NOLOAD) : { *(.debug_info) }
.debug_abbrev BLOCK(__section_alignment__) (NOLOAD) : { *(.debug_abbrev) }
.debug_line BLOCK(__section_alignment__) (NOLOAD) : { *(.debug_line) }
.debug_frame BLOCK(__section_alignment__) (NOLOAD) : { *(.debug_frame) }
.debug_str BLOCK(__section_alignment__) (NOLOAD) : { *(.debug_str) }
.debug_loc BLOCK(__section_alignment__) (NOLOAD) : { *(.debug_loc) }
.debug_macinfo BLOCK(__section_alignment__) (NOLOAD) : { *(.debug_macinfo) }
.debug_macinfo BLOCK(__section_alignment__) (NOLOAD) : { *(.debug_macinfo) }
.debug_ranges BLOCK(__section_alignment__) (NOLOAD) : { *(.debug_ranges) }
.cygheap BLOCK(64 * 1024) :
{
__system_dlls__ = ABSOLUTE(.) ;
__cygheap_start = ABSOLUTE(.) ;
__cygheap_mid = .;
. = ALIGN(512 * 1024, 0x10000);
. += 8192; /* inexplicably needed for alignment on 64K boundary?!? */
_cygheap_foo = .;
}
__cygheap_end = ABSOLUTE(.);
}

View File

@ -1030,7 +1030,7 @@ do_exit (int status)
if (exit_state < ES_CLOSEALL)
{
exit_state = ES_CLOSEALL;
close_all_files ();
close_all_files (false);
}
if (exit_state < ES_SIGPROCTERMINATE)

View File

@ -766,7 +766,7 @@ dtable::vfork_parent_restore ()
lock ();
fhandler_tty_slave *ctty_on_hold = cygheap->ctty_on_hold;
close_all_files ();
close_all_files (false);
fhandler_base **deleteme = fds;
fds = fds_on_hold;
fds_on_hold = NULL;

View File

@ -84,7 +84,7 @@ public:
fhandler_base **add_archetype ();
void delete_archetype (fhandler_base *);
friend void dtable_init ();
friend void __stdcall close_all_files ();
friend void __stdcall close_all_files (bool);
friend class cygheap_fdmanip;
friend class cygheap_fdget;
friend class cygheap_fdnew;

View File

@ -82,7 +82,7 @@ enum query_state {
class fhandler_base
{
friend class dtable;
friend void close_all_files ();
friend void close_all_files (bool);
struct status_flags
{

View File

@ -81,7 +81,11 @@ fork_copy (PROCESS_INFORMATION &pi, const char *what, ...)
DWORD done = 0;
if (here + todo > high)
todo = high - here;
int res = WriteProcessMemory (pi.hProcess, here, here, todo, &done);
int res;
if (pi.hThread)
res = WriteProcessMemory (pi.hProcess, here, here, todo, &done);
else
res = ReadProcessMemory (pi.hProcess, here, here, todo, &done);
debug_printf ("child handle %p, low %p, high %p, res %d", pi.hProcess,
low, high, res);
if (!res || todo != done)
@ -223,18 +227,15 @@ fork_child (HANDLE& hParent, dll *&first_dll, bool& load_dlls)
if (!load_dlls)
{
cygheap->fdtab.fixup_after_fork (hParent);
ProtectHandleINH (hParent);
sync_with_parent ("performed fork fixup", false);
}
else
{
dlls.load_after_fork (hParent, first_dll);
cygheap->fdtab.fixup_after_fork (hParent);
ProtectHandleINH (hParent);
sync_with_parent ("loaded dlls", true);
}
ForceCloseHandle (hParent);
(void) ForceCloseHandle1 (fork_info->forker_finished, forker_finished);
_my_tls.fixup_after_fork ();
@ -276,8 +277,7 @@ slow_pid_reuse (HANDLE h)
#endif
static int __stdcall
fork_parent (HANDLE& hParent, dll *&first_dll,
bool& load_dlls, void *stack_here, child_info_fork &ch)
fork_parent (HANDLE&, dll *&first_dll, bool& load_dlls, void *stack_here, child_info_fork &ch)
{
HANDLE forker_finished;
DWORD rc;
@ -308,16 +308,6 @@ fork_parent (HANDLE& hParent, dll *&first_dll,
if (cygheap->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, TRUE,
DUPLICATE_SAME_ACCESS))
{
system_printf ("couldn't create handle to myself for child, %E");
return -1;
}
/* Remember the address of the first loaded dll and decide
if we need to load dlls. We do this here so that this
information will be available in the parent and, when
@ -331,7 +321,6 @@ fork_parent (HANDLE& hParent, dll *&first_dll,
forker_finished = CreateEvent (&sec_all, FALSE, FALSE, NULL);
if (forker_finished == NULL)
{
CloseHandle (hParent);
system_printf ("unable to allocate forker_finished event, %E");
return -1;
}
@ -349,13 +338,9 @@ fork_parent (HANDLE& hParent, dll *&first_dll,
/* Remove impersonation */
cygheap->user.deimpersonate ();
ch.parent = hParent;
syscall_printf ("CreateProcess (%s, %s, 0, 0, 1, %x, 0, 0, %p, %p)",
myself->progname, myself->progname, c_flags, &si, &pi);
bool locked = __malloc_lock ();
void *newheap;
newheap = cygheap_setup_for_child (&ch, cygheap->fdtab.need_fixup_before ());
rc = CreateProcess (myself->progname, /* image to run */
myself->progname, /* what we send in arg0 */
&sec_none_nih,
@ -367,8 +352,6 @@ fork_parent (HANDLE& hParent, dll *&first_dll,
&si,
&pi);
CloseHandle (hParent);
if (!rc)
{
__seterrno ();
@ -376,19 +359,15 @@ fork_parent (HANDLE& hParent, dll *&first_dll,
ForceCloseHandle (forker_finished);
/* Restore impersonation */
cygheap->user.reimpersonate ();
cygheap_setup_for_child_cleanup (newheap, &ch, 0);
__malloc_unlock ();
return -1;
}
/* Fixup the parent datastructure if needed and resume the child's
main thread. */
if (!cygheap->fdtab.need_fixup_before ())
cygheap_setup_for_child_cleanup (newheap, &ch, 0);
else
if (cygheap->fdtab.need_fixup_before ())
{
cygheap->fdtab.fixup_before_fork (pi.dwProcessId);
cygheap_setup_for_child_cleanup (newheap, &ch, 1);
ResumeThread (pi.hThread);
}
@ -542,15 +521,15 @@ fork ()
{
struct
{
HANDLE hParent;
dll *first_dll;
bool load_dlls;
child_info_fork ch;
} grouped;
MALLOC_CHECK;
debug_printf ("entering");
grouped.hParent = grouped.first_dll = NULL;
grouped.first_dll = NULL;
grouped.load_dlls = 0;
void *esp;
@ -558,19 +537,20 @@ fork ()
myself->set_has_pgid_children ();
child_info_fork ch;
if (ch.subproc_ready == NULL)
if (grouped.ch.parent == NULL)
return -1;
if (grouped.ch.subproc_ready == NULL)
{
system_printf ("unable to allocate subproc_ready event, %E");
return -1;
}
sig_send (NULL, __SIGHOLD);
int res = setjmp (ch.jmp);
int res = setjmp (grouped.ch.jmp);
if (res)
res = fork_child (grouped.hParent, grouped.first_dll, grouped.load_dlls);
res = fork_child (grouped.ch.parent, grouped.first_dll, grouped.load_dlls);
else
res = fork_parent (grouped.hParent, grouped.first_dll, grouped.load_dlls, esp, ch);
res = fork_parent (grouped.ch.parent, grouped.first_dll, grouped.load_dlls, esp, grouped.ch);
sig_send (NULL, __SIGNOHOLD);
MALLOC_CHECK;
@ -664,3 +644,14 @@ vfork ()
return pid;
#endif
}
int
child_copy (HANDLE h, DWORD pid, const char *what, void *child_start, void *child_end)
{
PROCESS_INFORMATION pi;
pi.hProcess = h;
pi.dwProcessId = pid;
pi.hThread = NULL;
debug_printf ("%s, start %p, end %p", what, child_start, child_end);
return fork_copy (pi, what, child_start, child_end, NULL);
}

View File

@ -737,12 +737,23 @@ child_info::child_info (unsigned in_cb, child_info_types chtype)
if (chtype != PROC_SPAWN)
subproc_ready = CreateEvent (&sec_all, FALSE, FALSE, NULL);
sigproc_printf ("subproc_ready %p", subproc_ready);
cygheap = ::cygheap;
cygheap_max = ::cygheap_max;
dwProcessId = myself->dwProcessId;
/* Create an inheritable handle to pass to the child process. This will
allow the child to duplicate handles from the parent to itself. */
parent = NULL;
if (!DuplicateHandle (hMainProc, hMainProc, hMainProc, &parent, 0, TRUE,
DUPLICATE_SAME_ACCESS))
system_printf ("couldn't create handle to myself for child, %E");
}
child_info::~child_info ()
{
if (subproc_ready)
CloseHandle (subproc_ready);
if (parent)
CloseHandle (parent);
}
child_info_fork::child_info_fork () :

View File

@ -390,12 +390,8 @@ spawn_guts (const char * prog_arg, const char *const *argv,
else
chtype = PROC_EXEC;
child_info_spawn ciresrv (chtype);
si.lpReserved2 = (LPBYTE) &ciresrv;
si.cbReserved2 = sizeof (ciresrv);
ciresrv.moreinfo = (cygheap_exec_info *) ccalloc (HEAP_1_EXEC, 1, sizeof (cygheap_exec_info));
ciresrv.moreinfo->old_title = NULL;
cygheap_exec_info *moreinfo = (cygheap_exec_info *) ccalloc (HEAP_1_EXEC, 1, sizeof (cygheap_exec_info));
moreinfo->old_title = NULL;
/* CreateProcess takes one long string that is the command line (sigh).
We need to quote any argument that has whitespace or embedded "'s. */
@ -600,16 +596,16 @@ spawn_guts (const char * prog_arg, const char *const *argv,
return -1;
}
ciresrv.moreinfo->argc = newargv.argc;
ciresrv.moreinfo->argv = newargv;
moreinfo->argc = newargv.argc;
moreinfo->argv = newargv;
if (mode != _P_OVERLAY ||
!DuplicateHandle (hMainProc, myself.shared_handle (), hMainProc,
&ciresrv.moreinfo->myself_pinfo, 0,
&moreinfo->myself_pinfo, 0,
TRUE, DUPLICATE_SAME_ACCESS))
ciresrv.moreinfo->myself_pinfo = NULL;
moreinfo->myself_pinfo = NULL;
else
VerifyHandle (ciresrv.moreinfo->myself_pinfo);
VerifyHandle (moreinfo->myself_pinfo);
skip_arg_parsing:
PROCESS_INFORMATION pi = {NULL, 0, 0, 0};
@ -665,13 +661,18 @@ spawn_guts (const char * prog_arg, const char *const *argv,
syscall_printf ("null_app_name %d (%s, %.9500s)", null_app_name, runpath, one_line.buf);
void *newheap;
cygbench ("spawn-guts");
cygheap->fdtab.set_file_pointers_for_exec ();
cygheap->user.deimpersonate ();
moreinfo->envp = build_env (envp, envblock, moreinfo->envc, real_path.iscygexec ());
child_info_spawn ciresrv (chtype);
ciresrv.moreinfo = moreinfo;
si.lpReserved2 = (LPBYTE) &ciresrv;
si.cbReserved2 = sizeof (ciresrv);
/* When ruid != euid we create the new process under the current original
account and impersonate in child, this way maintaining the different
effective vs. real ids.
@ -682,9 +683,6 @@ spawn_guts (const char * prog_arg, const char *const *argv,
&& cygheap->user.saved_gid == cygheap->user.real_gid
&& !cygheap->user.groups.issetgroups ()))
{
ciresrv.moreinfo->envp = build_env (envp, envblock, ciresrv.moreinfo->envc,
real_path.iscygexec ());
newheap = cygheap_setup_for_child (&ciresrv, cygheap->fdtab.need_fixup_before ());
rc = CreateProcess (runpath, /* image name - with full path */
one_line.buf, /* what was passed to exec */
&sec_none_nih,/* process security attrs */
@ -719,9 +717,6 @@ spawn_guts (const char * prog_arg, const char *const *argv,
strcat (wstname, dskname);
si.lpDesktop = wstname;
ciresrv.moreinfo->envp = build_env (envp, envblock, ciresrv.moreinfo->envc,
real_path.iscygexec ());
newheap = cygheap_setup_for_child (&ciresrv, cygheap->fdtab.need_fixup_before ());
rc = CreateProcessAsUser (cygheap->user.primary_token (),
runpath, /* image name - with full path */
one_line.buf, /* what was passed to exec */
@ -758,7 +753,6 @@ spawn_guts (const char * prog_arg, const char *const *argv,
myself->sendsig = myself->exec_sendsig;
myself->exec_sendsig = NULL;
}
cygheap_setup_for_child_cleanup (newheap, &ciresrv, 0);
return -1;
}
@ -779,13 +773,8 @@ spawn_guts (const char * prog_arg, const char *const *argv,
/* Fixup the parent data structures if needed and resume the child's
main thread. */
if (!cygheap->fdtab.need_fixup_before ())
cygheap_setup_for_child_cleanup (newheap, &ciresrv, 0);
else
{
if (cygheap->fdtab.need_fixup_before ())
cygheap->fdtab.fixup_before_exec (pi.dwProcessId);
cygheap_setup_for_child_cleanup (newheap, &ciresrv, 1);
}
if (mode != _P_OVERLAY)
cygpid = cygwin_pid (pi.dwProcessId);
@ -807,7 +796,7 @@ spawn_guts (const char * prog_arg, const char *const *argv,
myself.hProcess = hExeced = pi.hProcess;
strcpy (myself->progname, real_path); // FIXME: race?
sigproc_printf ("new process name %s", myself->progname);
close_all_files ();
close_all_files (true);
/* If wr_proc_pipe doesn't exist then this process was not started by a cygwin
process. So, we need to wait around until the process we've just "execed"
dies. Use our own wait facility to wait for our own pid to exit (there

View File

@ -94,7 +94,7 @@ static int __stdcall stat_worker (const char *name, struct __stat64 *buf,
ensure we don't leave any such files lying around. */
void __stdcall
close_all_files ()
close_all_files (bool keep_table)
{
cygheap->fdtab.lock ();
@ -106,6 +106,7 @@ close_all_files ()
debug_printf ("closing fd %d", i);
#endif
fh->close ();
if (!keep_table)
cygheap->fdtab.release (i);
}

View File

@ -221,7 +221,7 @@ void uinfo_init (void);
void events_init (void);
void events_terminate (void);
void __stdcall close_all_files ();
void __stdcall close_all_files (bool);
/* Globals that handle initialization of winsock in a child process. */
extern HANDLE wsock32_handle;
@ -298,6 +298,7 @@ extern void multiple_cygwin_problem (const char *, unsigned, unsigned);
extern "C" void vklog (int priority, const char *message, va_list ap);
extern "C" void klog (int priority, const char *message, ...);
int child_copy (HANDLE, DWORD, const char *, void *, void *);
int symlink_worker (const char *, const char *, bool, bool)
__attribute__ ((regparm (3)));