Welcome to mirror list, hosted at ThFree Co, Russian Federation.

cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristopher Faylor <me@cgf.cx>2000-07-15 06:48:11 +0400
committerChristopher Faylor <me@cgf.cx>2000-07-15 06:48:11 +0400
commit2eb392bd77de1535823daeae04c83fae0e331ee8 (patch)
tree4884c02f41340bb1267f1566f004e76a90599d4e /winsup/cygwin
parent44d2afed74351bafed8c4f4d4e5664e50a9c9a9c (diff)
* 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.
Diffstat (limited to 'winsup/cygwin')
-rw-r--r--winsup/cygwin/ChangeLog24
-rw-r--r--winsup/cygwin/dcrt0.cc36
-rw-r--r--winsup/cygwin/dlfcn.cc3
-rw-r--r--winsup/cygwin/dll_init.cc537
-rw-r--r--winsup/cygwin/dll_init.h147
-rw-r--r--winsup/cygwin/dtable.cc6
-rw-r--r--winsup/cygwin/environ.cc10
-rw-r--r--winsup/cygwin/exec.cc13
-rw-r--r--winsup/cygwin/fork.cc81
-rw-r--r--winsup/cygwin/lib/_cygwin_crt0_common.cc5
-rw-r--r--winsup/cygwin/lib/cygwin_attach_dll.c12
-rw-r--r--winsup/cygwin/spawn.cc8
-rw-r--r--winsup/cygwin/winsup.h3
13 files changed, 408 insertions, 477 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index 82d841125..d934eea49 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -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>
* debug.cc (thread_stub): Use impure_ptr in place of reent_data.
diff --git a/winsup/cygwin/dcrt0.cc b/winsup/cygwin/dcrt0.cc
index a42e84e1b..4dddd31b3 100644
--- a/winsup/cygwin/dcrt0.cc
+++ b/winsup/cygwin/dcrt0.cc
@@ -40,6 +40,7 @@ BOOL strip_title_path = FALSE;
BOOL allow_glob = TRUE;
HANDLE NO_COPY parent_alive = NULL;
+int cygwin_finished_initializing = 0;
/* Used in SIGTOMASK for generating a bit for insertion into a sigset_t.
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. */
unsigned int signal_shift_subtract = 1;
-#ifdef _MT_SAFE
ResourceLocks _reslock NO_COPY;
MTinterface _mtinterf NO_COPY;
-#endif
extern "C"
{
@@ -64,6 +63,7 @@ extern "C"
/* This is an exported copy of environ which can be used by DLLs
which use cygwin.dll. */
char **__cygwin_environ;
+ char ***main_environ;
/* __progname used in getopt error message */
char *__progname = NULL;
struct _reent reent_data;
@@ -192,7 +192,7 @@ host_dependent_constants::init ()
{
case winNT:
win32_upper = 0xffffffff;
- shared = FILE_SHARE_READ | FILE_SHARE_WRITE;
+ shared = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE;
break;
case win98:
@@ -699,16 +699,8 @@ dll_crt0_1 ()
of the calls below (eg. uinfo_init) do stdio calls - this area must
be set to zero before then. */
-#ifdef _MT_SAFE
user_data->threadinterface->ClearReent();
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 ();
@@ -734,7 +726,10 @@ dll_crt0_1 ()
/* beyond this we only do for cygwin apps or dlls */
if (dynamically_loaded)
- return;
+ {
+ cygwin_finished_initializing = 1;
+ return;
+ }
/* Initialize signal/subprocess handling. */
sigproc_init ();
@@ -766,15 +761,14 @@ dll_crt0_1 ()
/* Set up __progname for getopt error call. */
__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
do this for noncygwin case since the signal thread is blocked due to
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 */
if (user_data->premain[PREMAIN_LEN / 2])
@@ -782,6 +776,9 @@ dll_crt0_1 ()
user_data->premain[i] (argc, argv);
debug_printf ("user_data->main %p", user_data->main);
+
+ set_errno (0);
+
if (user_data->main)
exit (user_data->main (argc, argv, *user_data->envptr));
}
@@ -806,6 +803,7 @@ _dll_crt0 ()
}
#endif
+ main_environ = user_data->envptr;
user_data->heapbase = user_data->heapptr = user_data->heaptop = NULL;
set_console_handler ();
@@ -874,7 +872,7 @@ void
dll_crt0 (per_process *uptr)
{
/* 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);
*(user_data->impure_ptr_ptr) = &reent_data;
diff --git a/winsup/cygwin/dlfcn.cc b/winsup/cygwin/dlfcn.cc
index cf74d4696..dc6fec321 100644
--- a/winsup/cygwin/dlfcn.cc
+++ b/winsup/cygwin/dlfcn.cc
@@ -183,13 +183,12 @@ dlopen (const char *name, int)
if (!name)
{
// handle for the current module
- ret = (void *) GetModuleHandle (0);
+ ret = (void *) GetModuleHandle (NULL);
}
else
{
// handle for the named library
const char *fullpath = get_full_path_of_dll (name);
- DllList::the().currentDlOpenedLib (fullpath);
ret = (void *) LoadLibrary (fullpath);
}
diff --git a/winsup/cygwin/dll_init.cc b/winsup/cygwin/dll_init.cc
index 0bf405fa4..94cc8e646 100644
--- a/winsup/cygwin/dll_init.cc
+++ b/winsup/cygwin/dll_init.cc
@@ -13,65 +13,28 @@ details. */
extern void __stdcall check_sanity_and_sync (per_process *);
-#ifdef _MT_SAFE
-extern ResourceLocks _reslock NO_COPY;
-extern MTinterface _mtinterf NO_COPY;
-#endif /*_MT_SAFE*/
+dll_list NO_COPY dlls;
-/* 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 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;
+static int dll_global_dtors_recorded = 0;
+/* Run destructors for all DLLs on exit. */
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
-doGlobalCTORS (per_process *p)
+/* Run all constructors associated with a dll */
+void
+per_module::run_ctors ()
{
- void (**pfunc)() = p->ctors;
+ void (**pfunc)() = ctors;
/* Run ctors backwards, so skip the first entry and find how many
there are, then run them. */
@@ -86,230 +49,160 @@ doGlobalCTORS (per_process *p)
}
}
-static void
-doGlobalDTORS (per_process *p)
+/* Run all destructors associated with a dll */
+void
+per_module::run_dtors ()
{
- if (!p)
- return;
- void (**pfunc)() = p->dtors;
+ void (**pfunc)() = dtors;
for (int i = 1; pfunc[i]; i++)
(pfunc[i]) ();
}
-#define INC 500
-
-static int
-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)
+/* Initialize an individual DLL */
+int
+dll::init ()
{
- /* FIXME: init environment (useful?) */
- *(p->envptr) = *(user_data->envptr);
+ int ret = 1;
- /* FIXME: need other initializations? */
+ /* Why didn't we just import this variable? */
+ *(p.envptr) = __cygwin_environ;
- int ret = 1;
- if (!_in_forkee)
+ /* Don't run constructors or the "main" if we've forked. */
+ if (!in_forkee)
{
/* global contructors */
- doGlobalCTORS (p);
+ p.run_ctors ();
/* entry point of dll (use main of per_process with null args...) */
- if (p->main)
- ret = (*(p->main)) (0, 0, 0);
+ if (p.main)
+ ret = (*(p.main)) (0, 0, 0);
}
return ret;
}
-DllList&
-DllList::the ()
+/* Look for a dll based on name */
+dll *
+dll_list::operator[] (const char *name)
{
- return _the;
-}
+ dll *d = &start;
+ while ((d = d->next) != NULL)
+ if (strcasematch (name, d->name))
+ return d;
-void
-DllList::currentDlOpenedLib (const char *name)
-{
- if (_dlopenedLib != 0)
- small_printf ("WARNING: previous dlopen of %s wasn't correctly performed\n", _dlopenedLib);
- _dlopenedLib = name;
- _dlopenIndex = -1;
+ return NULL;
}
-int
-DllList::recordDll (HMODULE h, per_process *p)
+#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)
{
- int ret = -1;
+ char name[MAX_PATH + 1];
+ DWORD namelen = GetModuleFileName (h, name, sizeof (name));
- /* debug_printf ("Record a dll p=%p\n", p); see WARNING */
- dllType type = LINK;
- if (_initCalled)
+ /* Already loaded? */
+ dll *d = dlls[name];
+ if (d)
{
- type = LOAD;
- _numberOfOpenedDlls++;
- forkeeMustReloadDlls (1);
+ d->count++; /* Yes. Bump the usage count. */
+ return d; /* Return previously allocated pointer. */
}
- if (_in_forkee)
+ int i;
+ void *s = p->bss_end;
+ MEMORY_BASIC_INFORMATION m;
+ /* Search for space after the DLL */
+ for (i = 0; i <= RETRIES; i++)
{
- ret = 0; // Just a flag
- goto out;
+ if (!VirtualQuery (s, &m, sizeof (m)))
+ return NULL; /* Can't do it. */
+ if (m.State == MEM_FREE)
+ break;
+ s = (char *) m.BaseAddress + m.RegionSize;
}
- 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;
+ /* 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
-DllList::detachDll (int dll_index)
+dll_list::detach (dll *d)
{
- if (dll_index != -1)
+ if (d->count <= 0)
+ system_printf ("WARNING: try to detach an already detached dll ...\n");
+ else if (--d->count == 0)
{
- dll *aDll = &(_list[dll_index]);
- doGlobalDTORS (&aDll->p);
- if (aDll->type == LOAD)
- _numberOfOpenedDlls--;
- aDll->type = NONE;
+ d->p.run_dtors ();
+ d->prev->next = d->next;
+ if (d->next)
+ d->next->prev = d->prev;
+ if (d->type == DLL_LOAD)
+ loaded_dlls--;
+ if (end == d)
+ end = d->prev;
+ UnmapViewOfFile (d);
}
- else
- small_printf ("WARNING: try to detach an already detached dll ...\n");
}
+/* Initialization called by dll_crt0_1. */
void
-DllList::initAll ()
+dll_list::init ()
{
- // init for destructors
- // because initAll isn't called in forked process, this exit function will
- // be recorded only once
- if (!__dll_global_dtors_recorded)
+ debug_printf ("here");
+ /* Make sure that destructors are called on exit. */
+ if (!dll_global_dtors_recorded)
{
- atexit (__dll_global_dtors);
- __dll_global_dtors_recorded = 1;
+ atexit (dll_global_dtors);
+ dll_global_dtors_recorded = 1;
}
- if (!_initCalled)
- {
- debug_printf ("call to DllList::initAll");
- for (int i = 0; i < _last; i++)
- {
- 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;
+ /* Walk the dll chain, initializing each dll */
+ dll *d = &start;
+ while ((d = d->next))
+ d->init ();
}
#define A64K (64 * 1024)
/* Mark every memory address up to "here" as reserved. This may force
Windows NT to load a DLL in the next available, lowest slot. */
-void
+static void
reserve_upto (const char *name, DWORD here)
{
DWORD size;
@@ -334,7 +227,7 @@ reserve_upto (const char *name, DWORD here)
/* Release all of the memory previously allocated by "upto" above.
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. */
-void
+static void
release_upto (const char *name, DWORD here)
{
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
and attempts to load them in the same place as they were loaded in the parent. */
void
-DllList::forkeeLoadDlls ()
+dll_list::load_after_fork (HANDLE parent, dll *first)
{
- _initCalled = 1;
- _in_forkee = 1;
+ in_forkee = 1;
int try2 = 0;
- for (int i = 0; i < _last; i++)
- 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)
- {
- FreeLibrary (h);
- LoadLibrary (name);
- }
- else if (try2)
- api_fatal ("unable to remap %s to same address as parent -- %p", name, h);
- else
- {
- FreeLibrary (h);
- reserve_upto (name, (DWORD) handle);
- try2 = 1;
- i--;
- continue;
- }
- if (try2)
- {
- release_upto (name, (DWORD) handle);
- try2 = 0;
- }
- }
- _in_forkee = 0;
-}
-
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-// iterators
+ dll d;
-DllListIterator::DllListIterator (int type) : _type (type), _index (-1)
-{
- operator++ ();
-}
-
-DllListIterator::~DllListIterator ()
-{
-}
-
-DllListIterator::operator per_process* ()
-{
- return &_list[index ()].p;
-}
-
-void
-DllListIterator::operator++ ()
-{
- _index++;
- while (_index < _last && (int) (_list[_index].type) != _type)
- _index++;
- if (_index == _last)
- _index = -1;
-}
-
-LinkedDllIterator::LinkedDllIterator () : DllListIterator ((int) LINK)
-{
-}
-
-LinkedDllIterator::~LinkedDllIterator ()
-{
-}
-
-LoadedDllIterator::LoadedDllIterator () : DllListIterator ((int) LOAD)
-{
-}
-
-LoadedDllIterator::~LoadedDllIterator ()
-{
+ void *next = first;
+ while (next)
+ {
+ DWORD nb;
+ /* Read the dll structure from the parent. */
+ if (!ReadProcessMemory (parent, next, &d, MAX_DLL_SIZE, &nb) ||
+ nb != MAX_DLL_SIZE)
+ return;
+ /* We're only interested in dynamically loaded dlls.
+ Hopefully, this function wouldn't even have been called unless
+ the parent had some of those. */
+ if (d.type == DLL_LOAD)
+ {
+ HMODULE h = LoadLibraryEx (d.name, NULL, DONT_RESOLVE_DLL_REFERENCES);
+
+ /* See if DLL will load in proper place. If so, free it and reload
+ it the right way.
+ It sort of stinks that we can't invert the order of the FreeLibrary
+ and LoadLibrary since Microsoft documentation seems to imply that that
+ should do what we want. However, since the library was loaded above,
+ The second LoadLibrary does not execute it's startup code unless it
+ is first unloaded. */
+ if (h == d.handle)
+ {
+ FreeLibrary (h);
+ LoadLibrary (d.name);
+ }
+ else if (try2)
+ api_fatal ("unable to remap %s to same address as parent -- %p", d.name, h);
+ else
+ {
+ /* 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
+ the same address space. In the "forked" process, the second DLL always
+ loads into a different location. */
+ FreeLibrary (h);
+ /* Block all of the memory up to the new load address. */
+ reserve_upto (d.name, (DWORD) d.handle);
+ try2 = 1; /* And try */
+ continue; /* again. */
+ }
+ /* If we reached here, and try2 is set, then there is a lot of memory to
+ release. */
+ if (try2)
+ {
+ release_upto (d.name, (DWORD) d.handle);
+ try2 = 0;
+ }
+ }
+ next = d.next; /* Get the address of the next DLL. */
+ }
+ in_forkee = 0;
}
extern "C" int
@@ -448,33 +322,70 @@ dll_dllcrt0 (HMODULE h, per_process *p)
/* Partially initialize Cygwin guts for non-cygwin apps. */
if (dynamically_loaded && user_data->magic_biscuit == 0)
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
future. Cygwin can now handle being loaded from a noncygwin app
using the same entry point. */
-extern "C"
-int
+extern "C" int
dll_noncygwin_dllcrt0 (HMODULE h, per_process *p)
{
return dll_dllcrt0 (h, p);
}
-extern "C"
-void
-cygwin_detach_dll (int dll_index)
+extern "C" void
+cygwin_detach_dll (dll *d)
{
- _the.detachDll (dll_index);
+ dlls.detach (d);
}
-extern "C"
-void
+extern "C" void
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;
+}
diff --git a/winsup/cygwin/dll_init.h b/winsup/cygwin/dll_init.h
index ca2cc2c20..ac1466803 100644
--- a/winsup/cygwin/dll_init.h
+++ b/winsup/cygwin/dll_init.h
@@ -1,6 +1,6 @@
/* dll_init.h
- Copyright 1998 Cygnus Solutions
+ Copyright 1998, 1999, 2000 Cygnus Solutions
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
details. */
-//-----------------------------------------------------------------------------
-// list of loaded DLL (used by fork & init)
-class DllList
+struct per_module
{
-public:
- static DllList& the ();
-
- // return dll index used for freeDll
- int recordDll (HMODULE, per_process*);
- void detachDll (int dll_index);
-
- // called after initialization of main module in dll_crt0
- void initAll ();
-
- // global destructors of loaded dlls
- void doGlobalDestructorsOfDlls ();
-
- // number of dlls dlopened
- int numberOfOpenedDlls ();
-
- // boolean to determine if forked process must reload dlls opened with
- // LoadLibrary or dlopen ...
- // default = 0 (FALSE)
- int forkeeMustReloadDlls ();
- void forkeeMustReloadDlls (int);
-
- void forkeeLoadDlls ();
-
- // set name of current library opened with dlopen
- void currentDlOpenedLib (const char*);
+ char ***envptr;
+ void (**ctors)(void);
+ void (**dtors)(void);
+ void *data_start;
+ void *data_end;
+ void *bss_start;
+ void *bss_end;
+ int (*main)(int, char **, char **);
+ per_module &operator = (per_process *p)
+ {
+ envptr = p->envptr;
+ ctors = p->ctors;
+ dtors = p->dtors;
+ data_start = p->data_start;
+ data_end = p->data_end;
+ bss_start = p->bss_start;
+ bss_end = p->bss_end;
+ main = p->main;
+ return *this;
+ }
+ void run_ctors ();
+ void run_dtors ();
};
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-class DllListIterator
+typedef enum
{
- int _type;
- int _index;
+ DLL_NONE,
+ DLL_LINK,
+ DLL_LOAD,
+ DLL_ANY
+} dll_type;
-protected:
- DllListIterator (int type);
- int index () const { return _index; }
-
-public:
- virtual ~DllListIterator();
-
- int ok() { return _index!=-1; }
- void operator++ ();
- void operator++ (int) { operator++ (); }
- operator per_process* ();
-};
-
-//-----------------------------------------------------------------------------
-
-class LinkedDllIterator : public DllListIterator
+struct dll
{
-public:
- LinkedDllIterator ();
- ~LinkedDllIterator ();
+ struct dll *next, *prev;
+ per_module p;
+ HMODULE handle;
+ int count;
+ dll_type type;
+ int namelen;
+ char name[MAX_PATH + 1];
+ void detach ();
+ int init ();
};
-//-----------------------------------------------------------------------------
+#define MAX_DLL_BEFORE_INIT 100
-class LoadedDllIterator : public DllListIterator
+class dll_list
{
+ dll *end;
+ dll *hold;
+ dll_type hold_type;
public:
- LoadedDllIterator ();
- ~LoadedDllIterator ();
+ dll start;
+ 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;
+ }
};
-//-----------------------------------------------------------------------------
-
-#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++; \
-} \
-}
-
+extern dll_list dlls;
diff --git a/winsup/cygwin/dtable.cc b/winsup/cygwin/dtable.cc
index 13167ccd1..4fb488d16 100644
--- a/winsup/cygwin/dtable.cc
+++ b/winsup/cygwin/dtable.cc
@@ -497,8 +497,8 @@ hinfo::linearize_fd_array (unsigned char *in_buf, int buflen)
LPBYTE
hinfo::de_linearize_fd_array (LPBYTE buf)
{
- int len;
- size_t max_used_fd, inc_size;
+ int len, max_used_fd;
+ size_t inc_size;
debug_printf ("buf %x", buf);
@@ -518,7 +518,7 @@ hinfo::de_linearize_fd_array (LPBYTE buf)
return NULL;
}
- for (size_t i = 0; i <= max_used_fd; i++)
+ for (int i = 0; i <= max_used_fd; i++)
{
/* 0xFF means closed */
if (*buf == 0xff)
diff --git a/winsup/cygwin/environ.cc b/winsup/cygwin/environ.cc
index 719a1712b..716af8547 100644
--- a/winsup/cygwin/environ.cc
+++ b/winsup/cygwin/environ.cc
@@ -13,7 +13,7 @@ details. */
#include <ctype.h>
#include <fcntl.h>
-#define environ (*user_data->envptr)
+#define environ __cygwin_environ
extern BOOL allow_glob;
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)
;
- __cygwin_environ = environ = (char **) realloc ((char *) environ,
- (size_t) (sizeof (char *) * (cnt + 2)));
+ environ = (char **) realloc ((char *) environ,
+ (size_t) (sizeof (char *) * (cnt + 2)));
if (!environ)
return -1;
environ[cnt + 1] = NULL;
+ update_envptrs ();
offset = cnt;
}
@@ -502,7 +503,8 @@ environ_init (int already_posix)
if (!sawTERM)
envp[i++] = strdup ("TERM=cygwin");
envp[i] = NULL;
- __cygwin_environ = environ = envp;
+ environ = envp;
+ update_envptrs ();
FreeEnvironmentStringsA ((char *) rawenv);
parse_options (NULL);
MALLOC_CHECK;
diff --git a/winsup/cygwin/exec.cc b/winsup/cygwin/exec.cc
index b83a9b905..0ba3ead6f 100644
--- a/winsup/cygwin/exec.cc
+++ b/winsup/cygwin/exec.cc
@@ -44,7 +44,7 @@ execl (const char *path, const char *arg0, ...)
while (argv[i++] != NULL);
va_end (args);
MALLOC_CHECK;
- return _execve (path, (char * const *) argv, *user_data->envptr);
+ return _execve (path, (char * const *) argv, __cygwin_environ);
}
extern "C"
@@ -52,7 +52,7 @@ int
execv (const char *path, char * const *argv)
{
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 */
@@ -85,7 +85,7 @@ sexecl (HANDLE hToken, const char *path, const char *arg0, ...)
va_end (args);
MALLOC_CHECK;
- return sexecve (hToken, path, (char * const *) argv, *user_data->envptr);
+ return sexecve (hToken, path, (char * const *) argv, __cygwin_environ);
}
extern "C"
@@ -131,8 +131,7 @@ sexeclp (HANDLE hToken, const char *path, const char *arg0, ...)
va_end (args);
MALLOC_CHECK;
- return sexecvpe (hToken, path, (const char * const *) argv,
- *user_data->envptr);
+ return sexecvpe (hToken, path, (const char * const *) argv, __cygwin_environ);
}
extern "C"
@@ -164,7 +163,7 @@ int
sexecv (HANDLE hToken, const char *path, const char * const *argv)
{
MALLOC_CHECK;
- return sexecve (hToken, path, argv, *user_data->envptr);
+ return sexecve (hToken, path, argv, __cygwin_environ);
}
extern "C"
@@ -172,7 +171,7 @@ int
sexecp (HANDLE hToken, const char *path, const char * const *argv)
{
MALLOC_CHECK;
- return sexecvpe (hToken, path, argv, *user_data->envptr);
+ return sexecvpe (hToken, path, argv, __cygwin_environ);
}
/*
diff --git a/winsup/cygwin/fork.cc b/winsup/cygwin/fork.cc
index 54c668137..fdd63c6e3 100644
--- a/winsup/cygwin/fork.cc
+++ b/winsup/cygwin/fork.cc
@@ -280,6 +280,13 @@ fork ()
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;
x = setjmp (ch.jmp);
@@ -457,43 +464,41 @@ fork ()
if (!rc)
goto cleanup;
- /* Now fill data/bss of linked dll */
- DO_LINKED_DLL (p)
- {
- 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;
+ /* Now fill data/bss of any DLLs that were linked into the program. */
+ 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", d->p.data_start, d->p.data_end,
+ d->p.bss_start, d->p.bss_end,
+ NULL))
+ goto cleanup;
+ }
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"))
+ !sync_with_child (pi, subproc_ready, load_dlls, "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)
+ /* 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)
{
- debug_printf ("copying data/bss for a loaded dll");
- if (!fork_copy (pi, "loaded dll data/bss", p->data_start, p->data_end,
- p->bss_start, p->bss_end,
- NULL))
- goto cleanup;
+ /* 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);
}
- DLL_DONE;
- /* Start the child up again. */
- (void) resume_child (pi, forker_finished);
- }
ForceCloseHandle (subproc_ready);
ForceCloseHandle (pi.hThread);
@@ -532,6 +537,14 @@ fork ()
char c;
if (GetEnvironmentVariable ("FORKDEBUG", &c, 1))
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
/* If we've played with the stack, stacksize != 0. That means that
@@ -548,20 +561,22 @@ fork ()
dtable.fixup_after_fork (hParent);
signal_fixup_after_fork ();
- ForceCloseHandle (hParent);
MALLOC_CHECK;
- /* reload dlls if necessary */
- if (!DllList::the().forkeeMustReloadDlls() ||
- !DllList::the().numberOfOpenedDlls())
+ /* If we haven't dynamically loaded any dlls, just signal
+ the parent. Otherwise, load all the dlls, tell the parent
+ 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);
else
{
- DllList::the().forkeeLoadDlls();
+ dlls.load_after_fork (hParent, first_dll);
sync_with_parent ("loaded dlls", TRUE);
}
+ ForceCloseHandle (hParent);
(void) ForceCloseHandle (child_proc_info->subproc_ready);
(void) ForceCloseHandle (child_proc_info->forker_finished);
diff --git a/winsup/cygwin/lib/_cygwin_crt0_common.cc b/winsup/cygwin/lib/_cygwin_crt0_common.cc
index fcca1694f..4ca6dd74e 100644
--- a/winsup/cygwin/lib/_cygwin_crt0_common.cc
+++ b/winsup/cygwin/lib/_cygwin_crt0_common.cc
@@ -56,10 +56,7 @@ _cygwin_crt0_common (MainFunc f, per_process *u)
u->ctors = &__CTOR_LIST__;
u->dtors = &__DTOR_LIST__;
- if (!u->envptr)
- u->envptr = &environ;
- else
- environ = *(u->envptr);
+ u->envptr = &environ;
if (uwasnull)
_impure_ptr = u->impure_ptr; /* Use field initialized in newer DLLs. */
else
diff --git a/winsup/cygwin/lib/cygwin_attach_dll.c b/winsup/cygwin/lib/cygwin_attach_dll.c
index 09b898bdf..440cace57 100644
--- a/winsup/cygwin/lib/cygwin_attach_dll.c
+++ b/winsup/cygwin/lib/cygwin_attach_dll.c
@@ -17,15 +17,9 @@ details. */
int
cygwin_attach_dll (HMODULE h, MainFunc f)
{
- struct per_process *u;
- if (_cygwin_crt0_common (f, NULL))
- 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);
- }
+ struct per_process u;
+ (void) _cygwin_crt0_common (f, &u);
/* jump into the dll. */
- return dll_dllcrt0 (h, u);
+ return dll_dllcrt0 (h, &u);
}
diff --git a/winsup/cygwin/spawn.cc b/winsup/cygwin/spawn.cc
index f6da86385..6ca82e413 100644
--- a/winsup/cygwin/spawn.cc
+++ b/winsup/cygwin/spawn.cc
@@ -894,7 +894,7 @@ spawnl (int mode, const char *path, const char *arg0, ...)
va_end (args);
return _spawnve (NULL, mode, path, (char * const *) argv,
- *user_data->envptr);
+ __cygwin_environ);
}
extern "C"
@@ -939,7 +939,7 @@ spawnlp (int mode, const char *path, const char *arg0, ...)
va_end (args);
- return spawnvpe (mode, path, (char * const *) argv, *user_data->envptr);
+ return spawnvpe (mode, path, (char * const *) argv, __cygwin_environ);
}
extern "C"
@@ -969,7 +969,7 @@ extern "C"
int
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"
@@ -984,7 +984,7 @@ extern "C"
int
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"
diff --git a/winsup/cygwin/winsup.h b/winsup/cygwin/winsup.h
index 61dd62786..5a1ff2ff1 100644
--- a/winsup/cygwin/winsup.h
+++ b/winsup/cygwin/winsup.h
@@ -323,6 +323,8 @@ extern HANDLE netapi32_handle;
extern "C" void error_start_init (const char*);
extern "C" int try_to_debug ();
+extern int cygwin_finished_initializing;
+
/**************************** Miscellaneous ******************************/
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);
+void __stdcall update_envptrs ();
char * __stdcall winenv (const char * const *, int);
extern char **__cygwin_environ;