* hinfo.cc (hinfo::linearize_fd_array): Make max_used_fd an int so that we can
detect when there are no fds to pass. * dcrt0.cc (host_dependent_constants::init): Revert Sat Mar 18 01:32:04 2000 change. (dll_crt0_1): Set "cygwin_finished_initializing" flag. (dll_crt0): Don't perform memcpy if uptr is already set to internal structure. (_dll_crt0): Remember location of programs envptr. * dll_init.h (per_module, dll, dll_list): Revamp. * dll_init.cc: Revamp. Use new classes. * fork.cc (fork): Use new revamped dll, dll_list, and per_module stuff. * environ.cc: Use __cygwin_environ throughout rather than the user_data->envptr. * exec.cc: Ditto. * spawn.cc: Ditto. * winsup.h: Declare update_envptrs, cygwin_finished_initializing. * lib/_cygwin_crt0_common.cc (_cygwin_crt0_common): Revert previous change. * lib/cygwin_attach_dll.cc (cygwin_attach_dll): Always pass in own per_process structure or we end up overwriting information from the main program.
This commit is contained in:
parent
44d2afed74
commit
2eb392bd77
|
@ -1,3 +1,27 @@
|
||||||
|
Fri Jul 14 22:40:22 2000 Christopher Faylor <cgf@cygnus.com>
|
||||||
|
|
||||||
|
* hinfo.cc (hinfo::linearize_fd_array): Make max_used_fd an int so that
|
||||||
|
we can detect when there are no fds to pass.
|
||||||
|
* dcrt0.cc (host_dependent_constants::init): Revert Sat Mar 18 01:32:04
|
||||||
|
2000 change.
|
||||||
|
(dll_crt0_1): Set "cygwin_finished_initializing" flag.
|
||||||
|
(dll_crt0): Don't perform memcpy if uptr is already set to internal
|
||||||
|
structure.
|
||||||
|
(_dll_crt0): Remember location of programs envptr.
|
||||||
|
* dll_init.h (per_module, dll, dll_list): Revamp.
|
||||||
|
* dll_init.cc: Revamp. Use new classes.
|
||||||
|
* fork.cc (fork): Use new revamped dll, dll_list, and per_module stuff.
|
||||||
|
* environ.cc: Use __cygwin_environ throughout rather than the
|
||||||
|
user_data->envptr.
|
||||||
|
* exec.cc: Ditto.
|
||||||
|
* spawn.cc: Ditto.
|
||||||
|
* winsup.h: Declare update_envptrs, cygwin_finished_initializing.
|
||||||
|
* lib/_cygwin_crt0_common.cc (_cygwin_crt0_common): Revert previous
|
||||||
|
change.
|
||||||
|
* lib/cygwin_attach_dll.cc (cygwin_attach_dll): Always pass in own
|
||||||
|
per_process structure or we end up overwriting information from the
|
||||||
|
main program.
|
||||||
|
|
||||||
Wed Jul 12 00:46:00 2000 Christopher Faylor <cgf@cygnus.com>
|
Wed Jul 12 00:46:00 2000 Christopher Faylor <cgf@cygnus.com>
|
||||||
|
|
||||||
* debug.cc (thread_stub): Use impure_ptr in place of reent_data.
|
* debug.cc (thread_stub): Use impure_ptr in place of reent_data.
|
||||||
|
|
|
@ -40,6 +40,7 @@ BOOL strip_title_path = FALSE;
|
||||||
BOOL allow_glob = TRUE;
|
BOOL allow_glob = TRUE;
|
||||||
|
|
||||||
HANDLE NO_COPY parent_alive = NULL;
|
HANDLE NO_COPY parent_alive = NULL;
|
||||||
|
int cygwin_finished_initializing = 0;
|
||||||
|
|
||||||
/* Used in SIGTOMASK for generating a bit for insertion into a sigset_t.
|
/* Used in SIGTOMASK for generating a bit for insertion into a sigset_t.
|
||||||
This is subtracted from the signal number prior to shifting the bit.
|
This is subtracted from the signal number prior to shifting the bit.
|
||||||
|
@ -49,10 +50,8 @@ HANDLE NO_COPY parent_alive = NULL;
|
||||||
measure to allow an orderly transfer to the new, correct sigmask method. */
|
measure to allow an orderly transfer to the new, correct sigmask method. */
|
||||||
unsigned int signal_shift_subtract = 1;
|
unsigned int signal_shift_subtract = 1;
|
||||||
|
|
||||||
#ifdef _MT_SAFE
|
|
||||||
ResourceLocks _reslock NO_COPY;
|
ResourceLocks _reslock NO_COPY;
|
||||||
MTinterface _mtinterf NO_COPY;
|
MTinterface _mtinterf NO_COPY;
|
||||||
#endif
|
|
||||||
|
|
||||||
extern "C"
|
extern "C"
|
||||||
{
|
{
|
||||||
|
@ -64,6 +63,7 @@ extern "C"
|
||||||
/* This is an exported copy of environ which can be used by DLLs
|
/* This is an exported copy of environ which can be used by DLLs
|
||||||
which use cygwin.dll. */
|
which use cygwin.dll. */
|
||||||
char **__cygwin_environ;
|
char **__cygwin_environ;
|
||||||
|
char ***main_environ;
|
||||||
/* __progname used in getopt error message */
|
/* __progname used in getopt error message */
|
||||||
char *__progname = NULL;
|
char *__progname = NULL;
|
||||||
struct _reent reent_data;
|
struct _reent reent_data;
|
||||||
|
@ -192,7 +192,7 @@ host_dependent_constants::init ()
|
||||||
{
|
{
|
||||||
case winNT:
|
case winNT:
|
||||||
win32_upper = 0xffffffff;
|
win32_upper = 0xffffffff;
|
||||||
shared = FILE_SHARE_READ | FILE_SHARE_WRITE;
|
shared = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case win98:
|
case win98:
|
||||||
|
@ -699,16 +699,8 @@ dll_crt0_1 ()
|
||||||
of the calls below (eg. uinfo_init) do stdio calls - this area must
|
of the calls below (eg. uinfo_init) do stdio calls - this area must
|
||||||
be set to zero before then. */
|
be set to zero before then. */
|
||||||
|
|
||||||
#ifdef _MT_SAFE
|
|
||||||
user_data->threadinterface->ClearReent();
|
user_data->threadinterface->ClearReent();
|
||||||
user_data->threadinterface->Init1();
|
user_data->threadinterface->Init1();
|
||||||
#else
|
|
||||||
memset (&reent_data, 0, sizeof (reent_data));
|
|
||||||
reent_data._errno = 0;
|
|
||||||
reent_data._stdin = reent_data.__sf + 0;
|
|
||||||
reent_data._stdout = reent_data.__sf + 1;
|
|
||||||
reent_data._stderr = reent_data.__sf + 2;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
char *line = GetCommandLineA ();
|
char *line = GetCommandLineA ();
|
||||||
|
|
||||||
|
@ -734,7 +726,10 @@ dll_crt0_1 ()
|
||||||
|
|
||||||
/* beyond this we only do for cygwin apps or dlls */
|
/* beyond this we only do for cygwin apps or dlls */
|
||||||
if (dynamically_loaded)
|
if (dynamically_loaded)
|
||||||
return;
|
{
|
||||||
|
cygwin_finished_initializing = 1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* Initialize signal/subprocess handling. */
|
/* Initialize signal/subprocess handling. */
|
||||||
sigproc_init ();
|
sigproc_init ();
|
||||||
|
@ -766,15 +761,14 @@ dll_crt0_1 ()
|
||||||
/* Set up __progname for getopt error call. */
|
/* Set up __progname for getopt error call. */
|
||||||
__progname = argv[0];
|
__progname = argv[0];
|
||||||
|
|
||||||
/* Call init of loaded dlls. */
|
|
||||||
DllList::the().initAll();
|
|
||||||
|
|
||||||
set_errno (0);
|
|
||||||
|
|
||||||
/* Flush signals and ensure that signal thread is up and running. Can't
|
/* Flush signals and ensure that signal thread is up and running. Can't
|
||||||
do this for noncygwin case since the signal thread is blocked due to
|
do this for noncygwin case since the signal thread is blocked due to
|
||||||
LoadLibrary serialization. */
|
LoadLibrary serialization. */
|
||||||
sig_send (NULL, __SIGFLUSH); /* also initializes uid, gid */
|
sig_send (NULL, __SIGFLUSH);
|
||||||
|
|
||||||
|
cygwin_finished_initializing = 1;
|
||||||
|
/* Call init of loaded dlls. */
|
||||||
|
dlls.init ();
|
||||||
|
|
||||||
/* Execute any specified "premain" functions */
|
/* Execute any specified "premain" functions */
|
||||||
if (user_data->premain[PREMAIN_LEN / 2])
|
if (user_data->premain[PREMAIN_LEN / 2])
|
||||||
|
@ -782,6 +776,9 @@ dll_crt0_1 ()
|
||||||
user_data->premain[i] (argc, argv);
|
user_data->premain[i] (argc, argv);
|
||||||
|
|
||||||
debug_printf ("user_data->main %p", user_data->main);
|
debug_printf ("user_data->main %p", user_data->main);
|
||||||
|
|
||||||
|
set_errno (0);
|
||||||
|
|
||||||
if (user_data->main)
|
if (user_data->main)
|
||||||
exit (user_data->main (argc, argv, *user_data->envptr));
|
exit (user_data->main (argc, argv, *user_data->envptr));
|
||||||
}
|
}
|
||||||
|
@ -806,6 +803,7 @@ _dll_crt0 ()
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
main_environ = user_data->envptr;
|
||||||
user_data->heapbase = user_data->heapptr = user_data->heaptop = NULL;
|
user_data->heapbase = user_data->heapptr = user_data->heaptop = NULL;
|
||||||
|
|
||||||
set_console_handler ();
|
set_console_handler ();
|
||||||
|
@ -874,7 +872,7 @@ void
|
||||||
dll_crt0 (per_process *uptr)
|
dll_crt0 (per_process *uptr)
|
||||||
{
|
{
|
||||||
/* Set the local copy of the pointer into the user space. */
|
/* Set the local copy of the pointer into the user space. */
|
||||||
if (uptr)
|
if (uptr && uptr != user_data)
|
||||||
{
|
{
|
||||||
memcpy (user_data, uptr, per_process_overwrite);
|
memcpy (user_data, uptr, per_process_overwrite);
|
||||||
*(user_data->impure_ptr_ptr) = &reent_data;
|
*(user_data->impure_ptr_ptr) = &reent_data;
|
||||||
|
|
|
@ -183,13 +183,12 @@ dlopen (const char *name, int)
|
||||||
if (!name)
|
if (!name)
|
||||||
{
|
{
|
||||||
// handle for the current module
|
// handle for the current module
|
||||||
ret = (void *) GetModuleHandle (0);
|
ret = (void *) GetModuleHandle (NULL);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// handle for the named library
|
// handle for the named library
|
||||||
const char *fullpath = get_full_path_of_dll (name);
|
const char *fullpath = get_full_path_of_dll (name);
|
||||||
DllList::the().currentDlOpenedLib (fullpath);
|
|
||||||
ret = (void *) LoadLibrary (fullpath);
|
ret = (void *) LoadLibrary (fullpath);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,65 +13,28 @@ details. */
|
||||||
|
|
||||||
extern void __stdcall check_sanity_and_sync (per_process *);
|
extern void __stdcall check_sanity_and_sync (per_process *);
|
||||||
|
|
||||||
#ifdef _MT_SAFE
|
dll_list NO_COPY dlls;
|
||||||
extern ResourceLocks _reslock NO_COPY;
|
|
||||||
extern MTinterface _mtinterf NO_COPY;
|
|
||||||
#endif /*_MT_SAFE*/
|
|
||||||
|
|
||||||
/* WARNING: debug can't be called before init !!!! */
|
static NO_COPY int in_forkee = 0;
|
||||||
|
/* local variables */
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// the private structure
|
|
||||||
|
|
||||||
typedef enum { NONE, LINK, LOAD } dllType;
|
|
||||||
|
|
||||||
struct dll
|
|
||||||
{
|
|
||||||
per_process p;
|
|
||||||
HMODULE handle;
|
|
||||||
const char *name;
|
|
||||||
dllType type;
|
|
||||||
};
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
#define MAX_DLL_BEFORE_INIT 100 // FIXME: enough ???
|
static int dll_global_dtors_recorded = 0;
|
||||||
static dll _list_before_init[MAX_DLL_BEFORE_INIT];
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// local variables
|
|
||||||
|
|
||||||
static DllList _the;
|
|
||||||
static int _last = 0;
|
|
||||||
static int _max = MAX_DLL_BEFORE_INIT;
|
|
||||||
static dll *_list = _list_before_init;
|
|
||||||
static int _initCalled = 0;
|
|
||||||
static int _numberOfOpenedDlls = 0;
|
|
||||||
static int _forkeeMustReloadDlls = 0;
|
|
||||||
static int _in_forkee = 0;
|
|
||||||
static const char *_dlopenedLib = 0;
|
|
||||||
static int _dlopenIndex = -1;
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
static int __dll_global_dtors_recorded = 0;
|
|
||||||
|
|
||||||
|
/* Run destructors for all DLLs on exit. */
|
||||||
static void
|
static void
|
||||||
__dll_global_dtors()
|
dll_global_dtors()
|
||||||
{
|
{
|
||||||
_the.doGlobalDestructorsOfDlls();
|
for (dll *d = dlls.istart (DLL_ANY); d; d = dlls.inext ())
|
||||||
|
d->p.run_dtors ();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
/* Run all constructors associated with a dll */
|
||||||
doGlobalCTORS (per_process *p)
|
void
|
||||||
|
per_module::run_ctors ()
|
||||||
{
|
{
|
||||||
void (**pfunc)() = p->ctors;
|
void (**pfunc)() = ctors;
|
||||||
|
|
||||||
/* Run ctors backwards, so skip the first entry and find how many
|
/* Run ctors backwards, so skip the first entry and find how many
|
||||||
there are, then run them. */
|
there are, then run them. */
|
||||||
|
@ -86,230 +49,160 @@ doGlobalCTORS (per_process *p)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
/* Run all destructors associated with a dll */
|
||||||
doGlobalDTORS (per_process *p)
|
void
|
||||||
|
per_module::run_dtors ()
|
||||||
{
|
{
|
||||||
if (!p)
|
void (**pfunc)() = dtors;
|
||||||
return;
|
|
||||||
void (**pfunc)() = p->dtors;
|
|
||||||
for (int i = 1; pfunc[i]; i++)
|
for (int i = 1; pfunc[i]; i++)
|
||||||
(pfunc[i]) ();
|
(pfunc[i]) ();
|
||||||
}
|
}
|
||||||
|
|
||||||
#define INC 500
|
/* Initialize an individual DLL */
|
||||||
|
int
|
||||||
static int
|
dll::init ()
|
||||||
add (HMODULE h, char *name, per_process *p, dllType type)
|
|
||||||
{
|
{
|
||||||
int ret = -1;
|
|
||||||
|
|
||||||
if (p)
|
|
||||||
check_sanity_and_sync (p);
|
|
||||||
|
|
||||||
if (_last == _max)
|
|
||||||
{
|
|
||||||
if (!_initCalled) // we try to load more than MAX_DLL_BEFORE_INIT
|
|
||||||
{
|
|
||||||
small_printf ("try to load more dll than max allowed=%d\n",
|
|
||||||
MAX_DLL_BEFORE_INIT);
|
|
||||||
ExitProcess (1);
|
|
||||||
}
|
|
||||||
|
|
||||||
dll* newArray = new dll[_max+INC];
|
|
||||||
if (_list)
|
|
||||||
{
|
|
||||||
memcpy (newArray, _list, _max * sizeof (dll));
|
|
||||||
if (_list != _list_before_init)
|
|
||||||
delete []_list;
|
|
||||||
}
|
|
||||||
_list = newArray;
|
|
||||||
_max += INC;
|
|
||||||
}
|
|
||||||
|
|
||||||
_list[_last].name = name && type == LOAD ? strdup (name) : NULL;
|
|
||||||
_list[_last].handle = h;
|
|
||||||
_list[_last].p = *p;
|
|
||||||
_list[_last].type = type;
|
|
||||||
|
|
||||||
ret = _last++;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
initOneDll (per_process *p)
|
|
||||||
{
|
|
||||||
/* FIXME: init environment (useful?) */
|
|
||||||
*(p->envptr) = *(user_data->envptr);
|
|
||||||
|
|
||||||
/* FIXME: need other initializations? */
|
|
||||||
|
|
||||||
int ret = 1;
|
int ret = 1;
|
||||||
if (!_in_forkee)
|
|
||||||
|
/* Why didn't we just import this variable? */
|
||||||
|
*(p.envptr) = __cygwin_environ;
|
||||||
|
|
||||||
|
/* Don't run constructors or the "main" if we've forked. */
|
||||||
|
if (!in_forkee)
|
||||||
{
|
{
|
||||||
/* global contructors */
|
/* global contructors */
|
||||||
doGlobalCTORS (p);
|
p.run_ctors ();
|
||||||
|
|
||||||
/* entry point of dll (use main of per_process with null args...) */
|
/* entry point of dll (use main of per_process with null args...) */
|
||||||
if (p->main)
|
if (p.main)
|
||||||
ret = (*(p->main)) (0, 0, 0);
|
ret = (*(p.main)) (0, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
DllList&
|
/* Look for a dll based on name */
|
||||||
DllList::the ()
|
dll *
|
||||||
|
dll_list::operator[] (const char *name)
|
||||||
{
|
{
|
||||||
return _the;
|
dll *d = &start;
|
||||||
|
while ((d = d->next) != NULL)
|
||||||
|
if (strcasematch (name, d->name))
|
||||||
|
return d;
|
||||||
|
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define RETRIES 100
|
||||||
|
|
||||||
|
/* Allocate space for a dll struct after the just-loaded dll. */
|
||||||
|
dll *
|
||||||
|
dll_list::alloc (HINSTANCE h, per_process *p, dll_type type)
|
||||||
|
{
|
||||||
|
char name[MAX_PATH + 1];
|
||||||
|
DWORD namelen = GetModuleFileName (h, name, sizeof (name));
|
||||||
|
|
||||||
|
/* Already loaded? */
|
||||||
|
dll *d = dlls[name];
|
||||||
|
if (d)
|
||||||
|
{
|
||||||
|
d->count++; /* Yes. Bump the usage count. */
|
||||||
|
return d; /* Return previously allocated pointer. */
|
||||||
|
}
|
||||||
|
|
||||||
|
int i;
|
||||||
|
void *s = p->bss_end;
|
||||||
|
MEMORY_BASIC_INFORMATION m;
|
||||||
|
/* Search for space after the DLL */
|
||||||
|
for (i = 0; i <= RETRIES; i++)
|
||||||
|
{
|
||||||
|
if (!VirtualQuery (s, &m, sizeof (m)))
|
||||||
|
return NULL; /* Can't do it. */
|
||||||
|
if (m.State == MEM_FREE)
|
||||||
|
break;
|
||||||
|
s = (char *) m.BaseAddress + m.RegionSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Couldn't find any. Uh oh. FIXME: Issue an error? */
|
||||||
|
if (i == RETRIES)
|
||||||
|
return NULL; /* Oh well */
|
||||||
|
|
||||||
|
SYSTEM_INFO s1;
|
||||||
|
GetSystemInfo (&s1);
|
||||||
|
|
||||||
|
/* Need to do the shared memory thing since W95 can't allocate in
|
||||||
|
the shared memory region otherwise. */
|
||||||
|
HANDLE h1 = CreateFileMapping (INVALID_HANDLE_VALUE, &sec_none_nih,
|
||||||
|
PAGE_READWRITE, 0, sizeof (dll), NULL);
|
||||||
|
|
||||||
|
DWORD n = (DWORD) m.BaseAddress;
|
||||||
|
n = ((n - (n % s1.dwAllocationGranularity)) + s1.dwAllocationGranularity);
|
||||||
|
d = (dll *) MapViewOfFileEx (h1, FILE_MAP_WRITE, 0, 0, 0, (void *) n);
|
||||||
|
CloseHandle (h1);
|
||||||
|
|
||||||
|
/* Now we've allocated a block of information. Fill it in with the supplied
|
||||||
|
info about this DLL. */
|
||||||
|
d->count = 1;
|
||||||
|
d->namelen = namelen;
|
||||||
|
strcpy (d->name, name);
|
||||||
|
d->handle = h;
|
||||||
|
d->p = p;
|
||||||
|
d->type = type;
|
||||||
|
if (end == NULL)
|
||||||
|
end = &start; /* Point to "end" of dll chain. */
|
||||||
|
end->next = d; /* Standard linked list stuff. */
|
||||||
|
d->next = NULL;
|
||||||
|
d->prev = end;
|
||||||
|
end = d;
|
||||||
|
tot++;
|
||||||
|
if (type == DLL_LOAD)
|
||||||
|
loaded_dlls++;
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Detach a DLL from the chain. */
|
||||||
void
|
void
|
||||||
DllList::currentDlOpenedLib (const char *name)
|
dll_list::detach (dll *d)
|
||||||
{
|
{
|
||||||
if (_dlopenedLib != 0)
|
if (d->count <= 0)
|
||||||
small_printf ("WARNING: previous dlopen of %s wasn't correctly performed\n", _dlopenedLib);
|
system_printf ("WARNING: try to detach an already detached dll ...\n");
|
||||||
_dlopenedLib = name;
|
else if (--d->count == 0)
|
||||||
_dlopenIndex = -1;
|
{
|
||||||
}
|
d->p.run_dtors ();
|
||||||
|
d->prev->next = d->next;
|
||||||
int
|
if (d->next)
|
||||||
DllList::recordDll (HMODULE h, per_process *p)
|
d->next->prev = d->prev;
|
||||||
{
|
if (d->type == DLL_LOAD)
|
||||||
int ret = -1;
|
loaded_dlls--;
|
||||||
|
if (end == d)
|
||||||
/* debug_printf ("Record a dll p=%p\n", p); see WARNING */
|
end = d->prev;
|
||||||
dllType type = LINK;
|
UnmapViewOfFile (d);
|
||||||
if (_initCalled)
|
}
|
||||||
{
|
|
||||||
type = LOAD;
|
|
||||||
_numberOfOpenedDlls++;
|
|
||||||
forkeeMustReloadDlls (1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_in_forkee)
|
|
||||||
{
|
|
||||||
ret = 0; // Just a flag
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
char buf[MAX_PATH];
|
|
||||||
GetModuleFileName (h, buf, MAX_PATH);
|
|
||||||
|
|
||||||
if (type == LOAD && _dlopenedLib !=0)
|
|
||||||
{
|
|
||||||
// it is not the current dlopened lib
|
|
||||||
// so we insert one empty lib to preserve place for current dlopened lib
|
|
||||||
if (!strcasematch (_dlopenedLib, buf))
|
|
||||||
{
|
|
||||||
if (_dlopenIndex == -1)
|
|
||||||
_dlopenIndex = add (0, 0, 0, NONE);
|
|
||||||
ret = add (h, buf, p, type);
|
|
||||||
}
|
|
||||||
else // it is the current dlopened lib
|
|
||||||
{
|
|
||||||
if (_dlopenIndex != -1)
|
|
||||||
{
|
|
||||||
_list[_dlopenIndex].handle = h;
|
|
||||||
_list[_dlopenIndex].p = *p;
|
|
||||||
_list[_dlopenIndex].type = type;
|
|
||||||
ret = _dlopenIndex;
|
|
||||||
_dlopenIndex = -1;
|
|
||||||
}
|
|
||||||
else // it this case the dlopened lib doesn't need other lib
|
|
||||||
ret = add (h, buf, p, type);
|
|
||||||
_dlopenedLib = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
ret = add (h, buf, p, type);
|
|
||||||
|
|
||||||
out:
|
|
||||||
if (_initCalled) // main module is already initialized
|
|
||||||
{
|
|
||||||
if (!initOneDll (p))
|
|
||||||
ret = -1;
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Initialization called by dll_crt0_1. */
|
||||||
void
|
void
|
||||||
DllList::detachDll (int dll_index)
|
dll_list::init ()
|
||||||
{
|
{
|
||||||
if (dll_index != -1)
|
debug_printf ("here");
|
||||||
|
/* Make sure that destructors are called on exit. */
|
||||||
|
if (!dll_global_dtors_recorded)
|
||||||
{
|
{
|
||||||
dll *aDll = &(_list[dll_index]);
|
atexit (dll_global_dtors);
|
||||||
doGlobalDTORS (&aDll->p);
|
dll_global_dtors_recorded = 1;
|
||||||
if (aDll->type == LOAD)
|
|
||||||
_numberOfOpenedDlls--;
|
|
||||||
aDll->type = NONE;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
small_printf ("WARNING: try to detach an already detached dll ...\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
DllList::initAll ()
|
|
||||||
{
|
|
||||||
// init for destructors
|
|
||||||
// because initAll isn't called in forked process, this exit function will
|
|
||||||
// be recorded only once
|
|
||||||
if (!__dll_global_dtors_recorded)
|
|
||||||
{
|
|
||||||
atexit (__dll_global_dtors);
|
|
||||||
__dll_global_dtors_recorded = 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!_initCalled)
|
/* Walk the dll chain, initializing each dll */
|
||||||
{
|
dll *d = &start;
|
||||||
debug_printf ("call to DllList::initAll");
|
while ((d = d->next))
|
||||||
for (int i = 0; i < _last; i++)
|
d->init ();
|
||||||
{
|
|
||||||
per_process *p = &_list[i].p;
|
|
||||||
if (p)
|
|
||||||
initOneDll (p);
|
|
||||||
}
|
|
||||||
_initCalled = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
DllList::doGlobalDestructorsOfDlls ()
|
|
||||||
{
|
|
||||||
// global destructors in reverse order
|
|
||||||
for (int i = _last - 1; i >= 0; i--)
|
|
||||||
{
|
|
||||||
if (_list[i].type != NONE)
|
|
||||||
{
|
|
||||||
per_process *p = &_list[i].p;
|
|
||||||
if (p)
|
|
||||||
doGlobalDTORS (p);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
DllList::numberOfOpenedDlls ()
|
|
||||||
{
|
|
||||||
return _numberOfOpenedDlls;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
DllList::forkeeMustReloadDlls ()
|
|
||||||
{
|
|
||||||
return _forkeeMustReloadDlls;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
DllList::forkeeMustReloadDlls (int i)
|
|
||||||
{
|
|
||||||
_forkeeMustReloadDlls = i;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#define A64K (64 * 1024)
|
#define A64K (64 * 1024)
|
||||||
|
|
||||||
/* Mark every memory address up to "here" as reserved. This may force
|
/* Mark every memory address up to "here" as reserved. This may force
|
||||||
Windows NT to load a DLL in the next available, lowest slot. */
|
Windows NT to load a DLL in the next available, lowest slot. */
|
||||||
void
|
static void
|
||||||
reserve_upto (const char *name, DWORD here)
|
reserve_upto (const char *name, DWORD here)
|
||||||
{
|
{
|
||||||
DWORD size;
|
DWORD size;
|
||||||
|
@ -334,7 +227,7 @@ reserve_upto (const char *name, DWORD here)
|
||||||
/* Release all of the memory previously allocated by "upto" above.
|
/* Release all of the memory previously allocated by "upto" above.
|
||||||
Note that this may also free otherwise reserved memory. If that becomes
|
Note that this may also free otherwise reserved memory. If that becomes
|
||||||
a problem, we'll have to keep track of the memory that we reserve above. */
|
a problem, we'll have to keep track of the memory that we reserve above. */
|
||||||
void
|
static void
|
||||||
release_upto (const char *name, DWORD here)
|
release_upto (const char *name, DWORD here)
|
||||||
{
|
{
|
||||||
DWORD size;
|
DWORD size;
|
||||||
|
@ -354,87 +247,68 @@ release_upto (const char *name, DWORD here)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define MAX_DLL_SIZE (sizeof (dll))
|
||||||
/* Reload DLLs after a fork. Iterates over the list of dynamically loaded DLLs
|
/* Reload DLLs after a fork. Iterates over the list of dynamically loaded DLLs
|
||||||
and attempts to load them in the same place as they were loaded in the parent. */
|
and attempts to load them in the same place as they were loaded in the parent. */
|
||||||
void
|
void
|
||||||
DllList::forkeeLoadDlls ()
|
dll_list::load_after_fork (HANDLE parent, dll *first)
|
||||||
{
|
{
|
||||||
_initCalled = 1;
|
in_forkee = 1;
|
||||||
_in_forkee = 1;
|
|
||||||
int try2 = 0;
|
int try2 = 0;
|
||||||
for (int i = 0; i < _last; i++)
|
dll d;
|
||||||
if (_list[i].type == LOAD)
|
|
||||||
{
|
|
||||||
const char *name = _list[i].name;
|
|
||||||
HMODULE handle = _list[i].handle;
|
|
||||||
HMODULE h = LoadLibraryEx (name, NULL, DONT_RESOLVE_DLL_REFERENCES);
|
|
||||||
|
|
||||||
if (h == handle)
|
void *next = first;
|
||||||
{
|
while (next)
|
||||||
FreeLibrary (h);
|
{
|
||||||
LoadLibrary (name);
|
DWORD nb;
|
||||||
}
|
/* Read the dll structure from the parent. */
|
||||||
else if (try2)
|
if (!ReadProcessMemory (parent, next, &d, MAX_DLL_SIZE, &nb) ||
|
||||||
api_fatal ("unable to remap %s to same address as parent -- %p", name, h);
|
nb != MAX_DLL_SIZE)
|
||||||
else
|
return;
|
||||||
{
|
/* We're only interested in dynamically loaded dlls.
|
||||||
FreeLibrary (h);
|
Hopefully, this function wouldn't even have been called unless
|
||||||
reserve_upto (name, (DWORD) handle);
|
the parent had some of those. */
|
||||||
try2 = 1;
|
if (d.type == DLL_LOAD)
|
||||||
i--;
|
{
|
||||||
continue;
|
HMODULE h = LoadLibraryEx (d.name, NULL, DONT_RESOLVE_DLL_REFERENCES);
|
||||||
}
|
|
||||||
if (try2)
|
|
||||||
{
|
|
||||||
release_upto (name, (DWORD) handle);
|
|
||||||
try2 = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_in_forkee = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
/* See if DLL will load in proper place. If so, free it and reload
|
||||||
//-----------------------------------------------------------------------------
|
it the right way.
|
||||||
// iterators
|
It sort of stinks that we can't invert the order of the FreeLibrary
|
||||||
|
and LoadLibrary since Microsoft documentation seems to imply that that
|
||||||
DllListIterator::DllListIterator (int type) : _type (type), _index (-1)
|
should do what we want. However, since the library was loaded above,
|
||||||
{
|
The second LoadLibrary does not execute it's startup code unless it
|
||||||
operator++ ();
|
is first unloaded. */
|
||||||
}
|
if (h == d.handle)
|
||||||
|
{
|
||||||
DllListIterator::~DllListIterator ()
|
FreeLibrary (h);
|
||||||
{
|
LoadLibrary (d.name);
|
||||||
}
|
}
|
||||||
|
else if (try2)
|
||||||
DllListIterator::operator per_process* ()
|
api_fatal ("unable to remap %s to same address as parent -- %p", d.name, h);
|
||||||
{
|
else
|
||||||
return &_list[index ()].p;
|
{
|
||||||
}
|
/* It loaded in the wrong place. Dunno why this happens but it always
|
||||||
|
seems to happen when there are multiple DLLs attempting to load into
|
||||||
void
|
the same address space. In the "forked" process, the second DLL always
|
||||||
DllListIterator::operator++ ()
|
loads into a different location. */
|
||||||
{
|
FreeLibrary (h);
|
||||||
_index++;
|
/* Block all of the memory up to the new load address. */
|
||||||
while (_index < _last && (int) (_list[_index].type) != _type)
|
reserve_upto (d.name, (DWORD) d.handle);
|
||||||
_index++;
|
try2 = 1; /* And try */
|
||||||
if (_index == _last)
|
continue; /* again. */
|
||||||
_index = -1;
|
}
|
||||||
}
|
/* If we reached here, and try2 is set, then there is a lot of memory to
|
||||||
|
release. */
|
||||||
LinkedDllIterator::LinkedDllIterator () : DllListIterator ((int) LINK)
|
if (try2)
|
||||||
{
|
{
|
||||||
}
|
release_upto (d.name, (DWORD) d.handle);
|
||||||
|
try2 = 0;
|
||||||
LinkedDllIterator::~LinkedDllIterator ()
|
}
|
||||||
{
|
}
|
||||||
}
|
next = d.next; /* Get the address of the next DLL. */
|
||||||
|
}
|
||||||
LoadedDllIterator::LoadedDllIterator () : DllListIterator ((int) LOAD)
|
in_forkee = 0;
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
LoadedDllIterator::~LoadedDllIterator ()
|
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" int
|
extern "C" int
|
||||||
|
@ -448,33 +322,70 @@ dll_dllcrt0 (HMODULE h, per_process *p)
|
||||||
/* Partially initialize Cygwin guts for non-cygwin apps. */
|
/* Partially initialize Cygwin guts for non-cygwin apps. */
|
||||||
if (dynamically_loaded && user_data->magic_biscuit == 0)
|
if (dynamically_loaded && user_data->magic_biscuit == 0)
|
||||||
dll_crt0 (p);
|
dll_crt0 (p);
|
||||||
return _the.recordDll (h, p);
|
|
||||||
|
if (p)
|
||||||
|
check_sanity_and_sync (p);
|
||||||
|
|
||||||
|
dll_type type;
|
||||||
|
|
||||||
|
/* If this function is called before cygwin has finished
|
||||||
|
initializing, then the DLL must be a cygwin-aware DLL
|
||||||
|
that was explicitly linked into the program rather than
|
||||||
|
a dlopened DLL. */
|
||||||
|
if (!cygwin_finished_initializing)
|
||||||
|
type = DLL_LINK;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
type = DLL_LOAD;
|
||||||
|
dlls.reload_on_fork = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Allocate and initialize space for the DLL. */
|
||||||
|
dll *d = dlls.alloc (h, p, type);
|
||||||
|
|
||||||
|
/* If d == NULL, then something is broken.
|
||||||
|
Otherwise, if we've finished initializing, it's ok to
|
||||||
|
initialize the DLL. If we haven't finished initializing,
|
||||||
|
it may not be safe to call the dll's "main" since not
|
||||||
|
all of cygwin's internal structures may have been set up. */
|
||||||
|
if (!d || (cygwin_finished_initializing && !d->init ()))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return (DWORD) d;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* OBSOLETE: This function is obsolescent and will go away in the
|
/* OBSOLETE: This function is obsolescent and will go away in the
|
||||||
future. Cygwin can now handle being loaded from a noncygwin app
|
future. Cygwin can now handle being loaded from a noncygwin app
|
||||||
using the same entry point. */
|
using the same entry point. */
|
||||||
|
|
||||||
extern "C"
|
extern "C" int
|
||||||
int
|
|
||||||
dll_noncygwin_dllcrt0 (HMODULE h, per_process *p)
|
dll_noncygwin_dllcrt0 (HMODULE h, per_process *p)
|
||||||
{
|
{
|
||||||
return dll_dllcrt0 (h, p);
|
return dll_dllcrt0 (h, p);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C"
|
extern "C" void
|
||||||
void
|
cygwin_detach_dll (dll *d)
|
||||||
cygwin_detach_dll (int dll_index)
|
|
||||||
{
|
{
|
||||||
_the.detachDll (dll_index);
|
dlls.detach (d);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C"
|
extern "C" void
|
||||||
void
|
|
||||||
dlfork (int val)
|
dlfork (int val)
|
||||||
{
|
{
|
||||||
_the.forkeeMustReloadDlls (val);
|
dlls.reload_on_fork = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
/* Called from various places to update all of the individual
|
||||||
//-----------------------------------------------------------------------------
|
ideas of the environ block. Explain to me again why we didn't
|
||||||
|
just import __cygwin_environ? */
|
||||||
|
void __stdcall
|
||||||
|
update_envptrs ()
|
||||||
|
{
|
||||||
|
extern char ***main_environ;
|
||||||
|
for (dll *d = dlls.istart (DLL_ANY); d; d = dlls.inext ())
|
||||||
|
{
|
||||||
|
*(d->p.envptr) = __cygwin_environ;
|
||||||
|
}
|
||||||
|
*main_environ = __cygwin_environ;
|
||||||
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* dll_init.h
|
/* dll_init.h
|
||||||
|
|
||||||
Copyright 1998 Cygnus Solutions
|
Copyright 1998, 1999, 2000 Cygnus Solutions
|
||||||
|
|
||||||
This file is part of Cygwin.
|
This file is part of Cygwin.
|
||||||
|
|
||||||
|
@ -8,95 +8,84 @@ This software is a copyrighted work licensed under the terms of the
|
||||||
Cygwin license. Please consult the file "CYGWIN_LICENSE" for
|
Cygwin license. Please consult the file "CYGWIN_LICENSE" for
|
||||||
details. */
|
details. */
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
struct per_module
|
||||||
// list of loaded DLL (used by fork & init)
|
|
||||||
class DllList
|
|
||||||
{
|
{
|
||||||
public:
|
char ***envptr;
|
||||||
static DllList& the ();
|
void (**ctors)(void);
|
||||||
|
void (**dtors)(void);
|
||||||
// return dll index used for freeDll
|
void *data_start;
|
||||||
int recordDll (HMODULE, per_process*);
|
void *data_end;
|
||||||
void detachDll (int dll_index);
|
void *bss_start;
|
||||||
|
void *bss_end;
|
||||||
// called after initialization of main module in dll_crt0
|
int (*main)(int, char **, char **);
|
||||||
void initAll ();
|
per_module &operator = (per_process *p)
|
||||||
|
{
|
||||||
// global destructors of loaded dlls
|
envptr = p->envptr;
|
||||||
void doGlobalDestructorsOfDlls ();
|
ctors = p->ctors;
|
||||||
|
dtors = p->dtors;
|
||||||
// number of dlls dlopened
|
data_start = p->data_start;
|
||||||
int numberOfOpenedDlls ();
|
data_end = p->data_end;
|
||||||
|
bss_start = p->bss_start;
|
||||||
// boolean to determine if forked process must reload dlls opened with
|
bss_end = p->bss_end;
|
||||||
// LoadLibrary or dlopen ...
|
main = p->main;
|
||||||
// default = 0 (FALSE)
|
return *this;
|
||||||
int forkeeMustReloadDlls ();
|
}
|
||||||
void forkeeMustReloadDlls (int);
|
void run_ctors ();
|
||||||
|
void run_dtors ();
|
||||||
void forkeeLoadDlls ();
|
|
||||||
|
|
||||||
// set name of current library opened with dlopen
|
|
||||||
void currentDlOpenedLib (const char*);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
class DllListIterator
|
typedef enum
|
||||||
{
|
{
|
||||||
int _type;
|
DLL_NONE,
|
||||||
int _index;
|
DLL_LINK,
|
||||||
|
DLL_LOAD,
|
||||||
|
DLL_ANY
|
||||||
|
} dll_type;
|
||||||
|
|
||||||
protected:
|
struct dll
|
||||||
DllListIterator (int type);
|
{
|
||||||
int index () const { return _index; }
|
struct dll *next, *prev;
|
||||||
|
per_module p;
|
||||||
public:
|
HMODULE handle;
|
||||||
virtual ~DllListIterator();
|
int count;
|
||||||
|
dll_type type;
|
||||||
int ok() { return _index!=-1; }
|
int namelen;
|
||||||
void operator++ ();
|
char name[MAX_PATH + 1];
|
||||||
void operator++ (int) { operator++ (); }
|
void detach ();
|
||||||
operator per_process* ();
|
int init ();
|
||||||
};
|
};
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
#define MAX_DLL_BEFORE_INIT 100
|
||||||
|
|
||||||
class LinkedDllIterator : public DllListIterator
|
class dll_list
|
||||||
{
|
{
|
||||||
|
dll *end;
|
||||||
|
dll *hold;
|
||||||
|
dll_type hold_type;
|
||||||
public:
|
public:
|
||||||
LinkedDllIterator ();
|
dll start;
|
||||||
~LinkedDllIterator ();
|
int tot;
|
||||||
|
int loaded_dlls;
|
||||||
|
int reload_on_fork;
|
||||||
|
dll *operator [] (const char *name);
|
||||||
|
dll *alloc (HINSTANCE, per_process *, dll_type);
|
||||||
|
void detach (dll *);
|
||||||
|
void init ();
|
||||||
|
void load_after_fork (HANDLE, dll *);
|
||||||
|
dll *istart (dll_type t)
|
||||||
|
{
|
||||||
|
hold_type = t;
|
||||||
|
hold = &start;
|
||||||
|
return inext ();
|
||||||
|
}
|
||||||
|
dll *inext ()
|
||||||
|
{
|
||||||
|
while ((hold = hold->next))
|
||||||
|
if (hold_type == DLL_ANY || hold->type == hold_type)
|
||||||
|
break;
|
||||||
|
return hold;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
extern dll_list dlls;
|
||||||
|
|
||||||
class LoadedDllIterator : public DllListIterator
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
LoadedDllIterator ();
|
|
||||||
~LoadedDllIterator ();
|
|
||||||
};
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
#define DO_LINKED_DLL(var) \
|
|
||||||
{ \
|
|
||||||
LinkedDllIterator iterator; \
|
|
||||||
while (iterator.ok ()) \
|
|
||||||
{ \
|
|
||||||
per_process *var = (per_process *) iterator;
|
|
||||||
|
|
||||||
#define DO_LOADED_DLL(var) \
|
|
||||||
{ \
|
|
||||||
LoadedDllIterator iterator; \
|
|
||||||
while (iterator.ok ()) \
|
|
||||||
{ \
|
|
||||||
per_process *var = (per_process *) iterator;
|
|
||||||
|
|
||||||
#define DLL_DONE \
|
|
||||||
iterator++; \
|
|
||||||
} \
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
|
@ -497,8 +497,8 @@ hinfo::linearize_fd_array (unsigned char *in_buf, int buflen)
|
||||||
LPBYTE
|
LPBYTE
|
||||||
hinfo::de_linearize_fd_array (LPBYTE buf)
|
hinfo::de_linearize_fd_array (LPBYTE buf)
|
||||||
{
|
{
|
||||||
int len;
|
int len, max_used_fd;
|
||||||
size_t max_used_fd, inc_size;
|
size_t inc_size;
|
||||||
|
|
||||||
debug_printf ("buf %x", buf);
|
debug_printf ("buf %x", buf);
|
||||||
|
|
||||||
|
@ -518,7 +518,7 @@ hinfo::de_linearize_fd_array (LPBYTE buf)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (size_t i = 0; i <= max_used_fd; i++)
|
for (int i = 0; i <= max_used_fd; i++)
|
||||||
{
|
{
|
||||||
/* 0xFF means closed */
|
/* 0xFF means closed */
|
||||||
if (*buf == 0xff)
|
if (*buf == 0xff)
|
||||||
|
|
|
@ -13,7 +13,7 @@ details. */
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
|
||||||
#define environ (*user_data->envptr)
|
#define environ __cygwin_environ
|
||||||
|
|
||||||
extern BOOL allow_glob;
|
extern BOOL allow_glob;
|
||||||
extern BOOL allow_ntea;
|
extern BOOL allow_ntea;
|
||||||
|
@ -228,11 +228,12 @@ setenv (const char *name, const char *value, int rewrite)
|
||||||
|
|
||||||
for (P = environ, cnt = 0; *P; ++P, ++cnt)
|
for (P = environ, cnt = 0; *P; ++P, ++cnt)
|
||||||
;
|
;
|
||||||
__cygwin_environ = environ = (char **) realloc ((char *) environ,
|
environ = (char **) realloc ((char *) environ,
|
||||||
(size_t) (sizeof (char *) * (cnt + 2)));
|
(size_t) (sizeof (char *) * (cnt + 2)));
|
||||||
if (!environ)
|
if (!environ)
|
||||||
return -1;
|
return -1;
|
||||||
environ[cnt + 1] = NULL;
|
environ[cnt + 1] = NULL;
|
||||||
|
update_envptrs ();
|
||||||
offset = cnt;
|
offset = cnt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -502,7 +503,8 @@ environ_init (int already_posix)
|
||||||
if (!sawTERM)
|
if (!sawTERM)
|
||||||
envp[i++] = strdup ("TERM=cygwin");
|
envp[i++] = strdup ("TERM=cygwin");
|
||||||
envp[i] = NULL;
|
envp[i] = NULL;
|
||||||
__cygwin_environ = environ = envp;
|
environ = envp;
|
||||||
|
update_envptrs ();
|
||||||
FreeEnvironmentStringsA ((char *) rawenv);
|
FreeEnvironmentStringsA ((char *) rawenv);
|
||||||
parse_options (NULL);
|
parse_options (NULL);
|
||||||
MALLOC_CHECK;
|
MALLOC_CHECK;
|
||||||
|
|
|
@ -44,7 +44,7 @@ execl (const char *path, const char *arg0, ...)
|
||||||
while (argv[i++] != NULL);
|
while (argv[i++] != NULL);
|
||||||
va_end (args);
|
va_end (args);
|
||||||
MALLOC_CHECK;
|
MALLOC_CHECK;
|
||||||
return _execve (path, (char * const *) argv, *user_data->envptr);
|
return _execve (path, (char * const *) argv, __cygwin_environ);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C"
|
extern "C"
|
||||||
|
@ -52,7 +52,7 @@ int
|
||||||
execv (const char *path, char * const *argv)
|
execv (const char *path, char * const *argv)
|
||||||
{
|
{
|
||||||
MALLOC_CHECK;
|
MALLOC_CHECK;
|
||||||
return _execve (path, (char * const *) argv, *user_data->envptr);
|
return _execve (path, (char * const *) argv, __cygwin_environ);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* the same as a standard exec() calls family, but with NT security support */
|
/* the same as a standard exec() calls family, but with NT security support */
|
||||||
|
@ -85,7 +85,7 @@ sexecl (HANDLE hToken, const char *path, const char *arg0, ...)
|
||||||
va_end (args);
|
va_end (args);
|
||||||
|
|
||||||
MALLOC_CHECK;
|
MALLOC_CHECK;
|
||||||
return sexecve (hToken, path, (char * const *) argv, *user_data->envptr);
|
return sexecve (hToken, path, (char * const *) argv, __cygwin_environ);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C"
|
extern "C"
|
||||||
|
@ -131,8 +131,7 @@ sexeclp (HANDLE hToken, const char *path, const char *arg0, ...)
|
||||||
va_end (args);
|
va_end (args);
|
||||||
|
|
||||||
MALLOC_CHECK;
|
MALLOC_CHECK;
|
||||||
return sexecvpe (hToken, path, (const char * const *) argv,
|
return sexecvpe (hToken, path, (const char * const *) argv, __cygwin_environ);
|
||||||
*user_data->envptr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C"
|
extern "C"
|
||||||
|
@ -164,7 +163,7 @@ int
|
||||||
sexecv (HANDLE hToken, const char *path, const char * const *argv)
|
sexecv (HANDLE hToken, const char *path, const char * const *argv)
|
||||||
{
|
{
|
||||||
MALLOC_CHECK;
|
MALLOC_CHECK;
|
||||||
return sexecve (hToken, path, argv, *user_data->envptr);
|
return sexecve (hToken, path, argv, __cygwin_environ);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C"
|
extern "C"
|
||||||
|
@ -172,7 +171,7 @@ int
|
||||||
sexecp (HANDLE hToken, const char *path, const char * const *argv)
|
sexecp (HANDLE hToken, const char *path, const char * const *argv)
|
||||||
{
|
{
|
||||||
MALLOC_CHECK;
|
MALLOC_CHECK;
|
||||||
return sexecvpe (hToken, path, argv, *user_data->envptr);
|
return sexecvpe (hToken, path, argv, __cygwin_environ);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -280,6 +280,13 @@ fork ()
|
||||||
return -1;
|
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
|
||||||
|
the stack is copied, in the child. */
|
||||||
|
dll *first_dll = dlls.start.next;
|
||||||
|
int load_dlls = dlls.reload_on_fork && dlls.loaded_dlls;
|
||||||
|
|
||||||
static child_info_fork ch;
|
static child_info_fork ch;
|
||||||
x = setjmp (ch.jmp);
|
x = setjmp (ch.jmp);
|
||||||
|
|
||||||
|
@ -457,43 +464,41 @@ fork ()
|
||||||
if (!rc)
|
if (!rc)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
/* Now fill data/bss of linked dll */
|
/* Now fill data/bss of any DLLs that were linked into the program. */
|
||||||
DO_LINKED_DLL (p)
|
for (dll *d = dlls.istart (DLL_LINK); d; d = dlls.inext ())
|
||||||
{
|
|
||||||
debug_printf ("copying data/bss of a linked dll");
|
|
||||||
if (!fork_copy (pi, "linked dll data/bss", p->data_start, p->data_end,
|
|
||||||
p->bss_start, p->bss_end,
|
|
||||||
NULL))
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
DLL_DONE;
|
|
||||||
|
|
||||||
proc_register (child);
|
|
||||||
int load_dll = DllList::the().forkeeMustReloadDlls() &&
|
|
||||||
DllList::the().numberOfOpenedDlls();
|
|
||||||
|
|
||||||
/* Start thread, and wait for it to reload dlls. */
|
|
||||||
if (!resume_child (pi, forker_finished) ||
|
|
||||||
!sync_with_child (pi, subproc_ready, load_dll, "child loading dlls"))
|
|
||||||
goto cleanup;
|
|
||||||
|
|
||||||
/* child reload dlls & then write their data and bss */
|
|
||||||
if (load_dll)
|
|
||||||
{
|
|
||||||
/* CHILD IS STOPPED */
|
|
||||||
/* write memory of reloaded dlls */
|
|
||||||
DO_LOADED_DLL (p)
|
|
||||||
{
|
{
|
||||||
debug_printf ("copying data/bss for a loaded dll");
|
debug_printf ("copying data/bss of a linked dll");
|
||||||
if (!fork_copy (pi, "loaded dll data/bss", p->data_start, p->data_end,
|
if (!fork_copy (pi, "linked dll data/bss", d->p.data_start, d->p.data_end,
|
||||||
p->bss_start, p->bss_end,
|
d->p.bss_start, d->p.bss_end,
|
||||||
NULL))
|
NULL))
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
DLL_DONE;
|
|
||||||
/* Start the child up again. */
|
proc_register (child);
|
||||||
(void) resume_child (pi, forker_finished);
|
|
||||||
}
|
/* 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"))
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
/* If DLLs were loaded in the parent, then the child has reloaded all
|
||||||
|
of them and is now waiting to have all of the individual data and
|
||||||
|
bss sections filled in. */
|
||||||
|
if (load_dlls)
|
||||||
|
{
|
||||||
|
/* CHILD IS STOPPED */
|
||||||
|
/* write memory of reloaded dlls */
|
||||||
|
for (dll *d = dlls.istart (DLL_LOAD); d; d = dlls.inext ())
|
||||||
|
{
|
||||||
|
debug_printf ("copying data/bss for a loaded dll");
|
||||||
|
if (!fork_copy (pi, "loaded dll data/bss", d->p.data_start, d->p.data_end,
|
||||||
|
d->p.bss_start, d->p.bss_end,
|
||||||
|
NULL))
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
/* Start the child up again. */
|
||||||
|
(void) resume_child (pi, forker_finished);
|
||||||
|
}
|
||||||
|
|
||||||
ForceCloseHandle (subproc_ready);
|
ForceCloseHandle (subproc_ready);
|
||||||
ForceCloseHandle (pi.hThread);
|
ForceCloseHandle (pi.hThread);
|
||||||
|
@ -532,6 +537,14 @@ fork ()
|
||||||
char c;
|
char c;
|
||||||
if (GetEnvironmentVariable ("FORKDEBUG", &c, 1))
|
if (GetEnvironmentVariable ("FORKDEBUG", &c, 1))
|
||||||
try_to_debug ();
|
try_to_debug ();
|
||||||
|
char buf[80];
|
||||||
|
/* This is useful for debugging fork problems. Use gdb to attach to
|
||||||
|
the pid reported here. */
|
||||||
|
if (GetEnvironmentVariable ("CYGWIN_FORK_SLEEP", buf, sizeof (buf)))
|
||||||
|
{
|
||||||
|
small_printf ("Sleeping %d after fork, pid %u\n", atoi (buf), GetCurrentProcessId ());
|
||||||
|
Sleep (atoi(buf));
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* If we've played with the stack, stacksize != 0. That means that
|
/* If we've played with the stack, stacksize != 0. That means that
|
||||||
|
@ -548,20 +561,22 @@ fork ()
|
||||||
|
|
||||||
dtable.fixup_after_fork (hParent);
|
dtable.fixup_after_fork (hParent);
|
||||||
signal_fixup_after_fork ();
|
signal_fixup_after_fork ();
|
||||||
ForceCloseHandle (hParent);
|
|
||||||
|
|
||||||
MALLOC_CHECK;
|
MALLOC_CHECK;
|
||||||
|
|
||||||
/* reload dlls if necessary */
|
/* If we haven't dynamically loaded any dlls, just signal
|
||||||
if (!DllList::the().forkeeMustReloadDlls() ||
|
the parent. Otherwise, load all the dlls, tell the parent
|
||||||
!DllList::the().numberOfOpenedDlls())
|
that we're done, and wait for the parent to fill in the.
|
||||||
|
loaded dlls' data/bss. */
|
||||||
|
if (!load_dlls)
|
||||||
sync_with_parent ("performed fork fixup.", FALSE);
|
sync_with_parent ("performed fork fixup.", FALSE);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
DllList::the().forkeeLoadDlls();
|
dlls.load_after_fork (hParent, first_dll);
|
||||||
sync_with_parent ("loaded dlls", TRUE);
|
sync_with_parent ("loaded dlls", TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ForceCloseHandle (hParent);
|
||||||
(void) ForceCloseHandle (child_proc_info->subproc_ready);
|
(void) ForceCloseHandle (child_proc_info->subproc_ready);
|
||||||
(void) ForceCloseHandle (child_proc_info->forker_finished);
|
(void) ForceCloseHandle (child_proc_info->forker_finished);
|
||||||
|
|
||||||
|
|
|
@ -56,10 +56,7 @@ _cygwin_crt0_common (MainFunc f, per_process *u)
|
||||||
|
|
||||||
u->ctors = &__CTOR_LIST__;
|
u->ctors = &__CTOR_LIST__;
|
||||||
u->dtors = &__DTOR_LIST__;
|
u->dtors = &__DTOR_LIST__;
|
||||||
if (!u->envptr)
|
u->envptr = &environ;
|
||||||
u->envptr = &environ;
|
|
||||||
else
|
|
||||||
environ = *(u->envptr);
|
|
||||||
if (uwasnull)
|
if (uwasnull)
|
||||||
_impure_ptr = u->impure_ptr; /* Use field initialized in newer DLLs. */
|
_impure_ptr = u->impure_ptr; /* Use field initialized in newer DLLs. */
|
||||||
else
|
else
|
||||||
|
|
|
@ -17,15 +17,9 @@ details. */
|
||||||
int
|
int
|
||||||
cygwin_attach_dll (HMODULE h, MainFunc f)
|
cygwin_attach_dll (HMODULE h, MainFunc f)
|
||||||
{
|
{
|
||||||
struct per_process *u;
|
struct per_process u;
|
||||||
if (_cygwin_crt0_common (f, NULL))
|
(void) _cygwin_crt0_common (f, &u);
|
||||||
u = NULL; /* Newer DLL. Use DLL internal per_process. */
|
|
||||||
else /* Older DLL. Provide a per_process */
|
|
||||||
{
|
|
||||||
u = (struct per_process *) alloca (sizeof (*u));
|
|
||||||
(void) _cygwin_crt0_common (f, u);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* jump into the dll. */
|
/* jump into the dll. */
|
||||||
return dll_dllcrt0 (h, u);
|
return dll_dllcrt0 (h, &u);
|
||||||
}
|
}
|
||||||
|
|
|
@ -894,7 +894,7 @@ spawnl (int mode, const char *path, const char *arg0, ...)
|
||||||
va_end (args);
|
va_end (args);
|
||||||
|
|
||||||
return _spawnve (NULL, mode, path, (char * const *) argv,
|
return _spawnve (NULL, mode, path, (char * const *) argv,
|
||||||
*user_data->envptr);
|
__cygwin_environ);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C"
|
extern "C"
|
||||||
|
@ -939,7 +939,7 @@ spawnlp (int mode, const char *path, const char *arg0, ...)
|
||||||
|
|
||||||
va_end (args);
|
va_end (args);
|
||||||
|
|
||||||
return spawnvpe (mode, path, (char * const *) argv, *user_data->envptr);
|
return spawnvpe (mode, path, (char * const *) argv, __cygwin_environ);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C"
|
extern "C"
|
||||||
|
@ -969,7 +969,7 @@ extern "C"
|
||||||
int
|
int
|
||||||
spawnv (int mode, const char *path, const char * const *argv)
|
spawnv (int mode, const char *path, const char * const *argv)
|
||||||
{
|
{
|
||||||
return _spawnve (NULL, mode, path, argv, *user_data->envptr);
|
return _spawnve (NULL, mode, path, argv, __cygwin_environ);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C"
|
extern "C"
|
||||||
|
@ -984,7 +984,7 @@ extern "C"
|
||||||
int
|
int
|
||||||
spawnvp (int mode, const char *path, const char * const *argv)
|
spawnvp (int mode, const char *path, const char * const *argv)
|
||||||
{
|
{
|
||||||
return spawnvpe (mode, path, argv, *user_data->envptr);
|
return spawnvpe (mode, path, argv, __cygwin_environ);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C"
|
extern "C"
|
||||||
|
|
|
@ -323,6 +323,8 @@ extern HANDLE netapi32_handle;
|
||||||
extern "C" void error_start_init (const char*);
|
extern "C" void error_start_init (const char*);
|
||||||
extern "C" int try_to_debug ();
|
extern "C" int try_to_debug ();
|
||||||
|
|
||||||
|
extern int cygwin_finished_initializing;
|
||||||
|
|
||||||
/**************************** Miscellaneous ******************************/
|
/**************************** Miscellaneous ******************************/
|
||||||
|
|
||||||
const char * __stdcall find_exec (const char *name, path_conv& buf, const char *winenv = "PATH=",
|
const char * __stdcall find_exec (const char *name, path_conv& buf, const char *winenv = "PATH=",
|
||||||
|
@ -473,6 +475,7 @@ struct win_env
|
||||||
|
|
||||||
win_env * __stdcall getwinenv (const char *name, const char *posix = NULL);
|
win_env * __stdcall getwinenv (const char *name, const char *posix = NULL);
|
||||||
|
|
||||||
|
void __stdcall update_envptrs ();
|
||||||
char * __stdcall winenv (const char * const *, int);
|
char * __stdcall winenv (const char * const *, int);
|
||||||
extern char **__cygwin_environ;
|
extern char **__cygwin_environ;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue