#include "winsup.h"
#include <psapi.h>
#include <stdlib.h>
+#include <dlfcn.h>
#include <ctype.h>
#include <wctype.h>
#include "path.h"
#include "fhandler.h"
#include "dtable.h"
+#include "dll_init.h"
#include "cygheap.h"
#include "perprocess.h"
-#include "dlfcn.h"
#include "cygtls.h"
#include "tls_pbuf.h"
#include "ntdll.h"
#endif
ret = (void *) LoadLibraryW (wpath);
+ /* reference counting */
+ if (ret)
+ {
+ dll *d = dlls.find (ret);
+ if (d)
+ ++d->count;
+ }
#ifndef __x86_64__
/* Restore original cxx_malloc pointer. */
extern "C" int
dlclose (void *handle)
{
- int ret;
- if (handle == GetModuleHandle (NULL))
- ret = 0;
- else if (FreeLibrary ((HMODULE) handle))
- ret = 0;
- else
- ret = -1;
+ int ret = 0;
+ if (handle != GetModuleHandle (NULL))
+ {
+ /* reference counting */
+ dll *d = dlls.find (handle);
+ if (d) system_printf ("%W count %d", d->name, d->count);
+ if (!d || d->count <= 0)
+ {
+ errno = ENOENT;
+ ret = -1;
+ }
+ else
+ {
+ --d->count;
+ if (!FreeLibrary ((HMODULE) handle))
+ {
+ __seterrno ();
+ ret = -1;
+ }
+ }
+ }
if (ret)
set_dl_error ("dlclose");
return ret;
dll *d = (type == DLL_LINK) ? dlls.find_by_modname (modname) : dlls[name];
if (d)
{
- if (!in_forkee)
- d->count++; /* Yes. Bump the usage count. */
- else if (d->handle != h)
+ /* We only get here in the forkee. */
+ if (d->handle != h)
fabort ("%W: Loaded to different address: parent(%p) != child(%p)",
name, d->handle, h);
/* If this DLL has been linked against, and the full path differs, try
}
else
{
- /* FIXME: Change this to new at some point. */
- d = (dll *) cmalloc (HEAP_2_DLL, sizeof (*d) + (namelen * sizeof (*name)));
-
+ d = (dll *) cmalloc (HEAP_2_DLL,
+ sizeof (*d) + (namelen * sizeof (*name)));
/* Now we've allocated a block of information. Fill it in with the
supplied info about this DLL. */
- d->count = 1;
wcscpy (d->name, name);
d->modname = d->name + (modname - name);
d->handle = h;
+ d->count = 0; /* Reference counting performed in dlopen/dlclose. */
d->has_dtors = true;
d->p = p;
d->ndeps = 0;
guard (true);
if ((d = find (retaddr)))
{
- if (d->count <= 0)
- system_printf ("WARNING: trying to detach an already detached dll ...");
- if (--d->count == 0)
- {
- /* Ensure our exception handler is enabled for destructors */
- exception protect;
- /* Call finalize function if we are not already exiting */
- if (!exit_state)
- __cxa_finalize (d->handle);
- d->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;
- cfree (d);
- }
+ system_printf ("HERE %W", d->name);
+ /* Ensure our exception handler is enabled for destructors */
+ exception protect;
+ /* Call finalize function if we are not already exiting */
+ if (!exit_state)
+ __cxa_finalize (d->handle);
+ d->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;
+ cfree (d);
}
guard (false);
}
if (h != d->handle)
fabort ("unable to map %W to same address as parent: %p != %p",
d->modname, d->handle, h);
+ /* Fix OS reference count. */
+ for (int cnt = 1; cnt < d->count; ++cnt)
+ LoadLibraryW (d->name);
}
}