+2007-09-04 Ralf Wildenhues <Ralf.Wildenhues@gmx.de>
+
+ * doc/libtool.texi (User defined module data)
+ <lt_dlinterface_register>: Document that a NULL place matches
+ all modules.
+ * libltdl/lt_dlloader.c (lt_dlloader_remove): Actually iterate
+ over all open modules when looking for modules that use it.
+ If a resident module is found, return but do not set the error
+ string.
+ * libltdl/ltdl.c (lt_dlexit): When removing dlloaders, ignore
+ errors that stem from earlier failed commands. Exposed by the
+ lt_dladvise test.
+ Fixes regression over branch-1-5.
+ Memleak report as Coverity CID 19 via Jeff Squyres.
+
2007-09-01 Ralf Wildenhues <Ralf.Wildenhues@gmx.de>
* NEWS: Update.
and in return obtain a unique key to store and retrieve per-module data.
You supply an @var{id_string} and @var{iface} so that the resulting
@code{lt_dlinterface_id} can be used to filter the module handles
-returned by the iteration functions below.
+returned by the iteration functions below. If @var{iface} is @code{NULL},
+all modules will be matched.
@end deftypefun
@deftypefun void lt_dlinterface_free (@w{lt_dlinterface_id @var{iface}})
/* Return the contents of the first item in the global loader list
with a matching NAME after removing it from that list. If there
was no match, return NULL; if there is an error, return NULL and
- set an error for lt_dlerror; in either case, the loader list is
- not changed if NULL is returned. */
+ set an error for lt_dlerror; do not set an error if only resident
+ modules need this loader; in either case, the loader list is not
+ changed if NULL is returned. */
lt_dlvtable *
lt_dlloader_remove (char *name)
{
const lt_dlvtable * vtable = lt_dlloader_find (name);
- lt__handle * handle = 0;
+ static const char id_string[] = "lt_dlloader_remove";
+ lt_dlinterface_id iface;
+ lt_dlhandle handle = 0;
+ int in_use = 0;
+ int in_use_by_resident = 0;
if (!vtable)
{
}
/* Fail if there are any open modules which use this loader. */
- for (handle = 0; handle; handle = handle->next)
+ iface = lt_dlinterface_register (id_string, NULL);
+ while ((handle = lt_dlhandle_iterate (iface, handle)))
{
- if (handle->vtable == vtable)
+ lt__handle *cur = (lt__handle *) handle;
+ if (cur->vtable == vtable)
{
- LT__SETERROR (REMOVE_LOADER);
- return 0;
+ in_use = 1;
+ if (lt_dlisresident (handle))
+ in_use_by_resident = 1;
}
}
+ lt_dlinterface_free (iface);
+ if (in_use)
+ {
+ if (!in_use_by_resident)
+ LT__SETERROR (REMOVE_LOADER);
+ return 0;
+ }
/* Call the loader finalisation function. */
if (vtable && vtable->dlloader_exit)
break;
}
+ /* When removing loaders, we can only find out failure by testing
+ the error string, so avoid a spurious one from an earlier
+ failed command. */
+ if (!errors)
+ LT__SETERRORSTR (0);
+
/* close all loaders */
for (loader = (lt_dlloader *) lt_dlloader_next (NULL); loader;)
{
}
else
{
- ++errors;
+ /* ignore errors due to resident modules */
+ const char *err;
+ LT__GETERROR (err);
+ if (err)
+ ++errors;
}
loader = next;