libtool-patches
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

277-gary-rename-remaining-troublesome-ltdl-apis.diff


From: Gary V. Vaughan
Subject: 277-gary-rename-remaining-troublesome-ltdl-apis.diff
Date: Sun, 18 Sep 2005 01:30:03 +0100

Okay to commit?

This fixes the remaining holes that allowed libltdl clients to stumble
across each others' loaded modules.  Of course, there is nothing to
prevent clients from registering a dumb interface validator that returns
other clients' modules... hopefully the extra stuff I've added to the
manual makes it clear how to do it properly though.

Once this is committed, we can remove another of the remaining release
blockers... :-D

Cheers,
        Gary.

 ChangeLog        |   11 +++
 NEWS             |    9 +-
 doc/libtool.texi |  176 +++++++++++++++++++++----------------------------------
 libltdl/ltdl.c   |   85 +++++++++-----------------
 libltdl/ltdl.h   |   10 +--
 5 files changed, 124 insertions(+), 167 deletions(-)

Index: libtool--devo--1.0/ChangeLog
===================================================================
--- libtool--devo--1.0.orig/ChangeLog
+++ libtool--devo--1.0/ChangeLog
@@ -1,3 +1,14 @@
+2005-09-18  Gary V. Vaughan  <address@hidden>
+
+       * libltdl/ltdl.h, libltdl/ltdl.c (lt_dlhandle_first): Removed.
+       * libltdl/ltdl.h, libltdl/ltdl.c (lt_dlhandle_next)
+       (lt_dlhandle_find, lt_dlforeach): Removed...
+       (lt_dlhandle_iterate, lt_dlhandle_fetch, lt_dlhandle_map): Similar
+       functions that are multi-loader safe, and require a registered
+       interface validator argument.
+       * doc/libtool.texi: Updated.
+       * NEWS: Updated.
+
 2005-09-17  Gary V. Vaughan  <address@hidden>
 
        * libltdl/ltdl.h (lt_ptr, lt_dlmutex_register, lt_dlmutex_lock)
Index: libtool--devo--1.0/NEWS
===================================================================
--- libtool--devo--1.0.orig/NEWS
+++ libtool--devo--1.0/NEWS
@@ -6,10 +6,13 @@ New in 1.9h: 2005-??-??; CVS version 2.1
 * New lt_dlinterface_register, lt_dlinterface_set_data and
   lt_dlinterface_get_data libltdl API calls to maintain separation of
   concerns between modules loaded by different libraries.
+* New multi-module-loader safe libltdl handle iteration APIs:
+  lt_dlhandle_iterate, lt_dlhandle_fetch, lt_dlhandle_map.
 * Removed deprecated APIs from libltdl: lt_dlcaller_register,
-  lt_dlcaller_get_data, lt_dlcaller_set_data, lt_ptr, lt_dlmutex_register,
-  lt_dlmutex_lock, lt_dlmutex_unlock, lt_dlmutex_seterror,
-  lt_dlmutex_geterror, lt_dlmalloc, lt_dlrealloc, lt_dlfree.
+  lt_dlcaller_get_data, lt_dlcaller_set_data, lt_dlhandle_next, lt_dlforeach,
+  lt_dlhandle_find, lt_ptr, lt_dlmutex_register, lt_dlmutex_lock,
+  lt_dlmutex_unlock, lt_dlmutex_seterror, lt_dlmutex_geterror, lt_dlmalloc,
+  lt_dlrealloc, lt_dlfree.
 * Support for Portland Group compiler on GNU/Linux.
 * Support for linux-dietlibc (`diet' as well as `diet-dyn', separately).
 * Shell optimizations which break use of the stdin file descriptor in libtool.
Index: libtool--devo--1.0/doc/libtool.texi
===================================================================
--- libtool--devo--1.0.orig/doc/libtool.texi
+++ libtool--devo--1.0/doc/libtool.texi
@@ -3735,35 +3735,85 @@ Furthermore, in order to save you from h
 handles of all the modules you have loaded, these functions allow you to
 iterate over libltdl's list of loaded modules:
 
address@hidden int lt_dlforeach (@w{int (address@hidden) (lt_dlhandle 
@var{handle}, void * @var{data})}, @w{void * @var{data}})
-For each loaded module call the function @var{func}.  The argument
address@hidden is the handle of one of the loaded modules, @var{data} is
-the @var{data} argument passed to @code{lt_dlforeach}.
-As soon as @var{func} returns a non-zero value for one of the handles,
address@hidden will stop calling @var{func} and immediately return 1.
-Otherwise 0 is returned.
address@hidden {Type} lt_dlinterface_id
+The opaque type used to hold the module interface details for each
+registered libltdl client..
address@hidden deftp
+
address@hidden {Type} int lt_dlhandle_interface (@w{lt_dlhandle @var{handle},} 
@w{const char address@hidden)
+Functions of this type are called to check that a handle conforms to a
+library's expected module interface when iterating over the global
+handle list.  You should be careful to write a callback function of
+this type that can correctly identify modules that belong to this
+client, both to prevent other clients from accidentally finding your
+loaded modules with the iterator functions below, and vice versa.  The
+best way of doing this is to check that module @var{handle} conforms
+to the interface specification of your loader using @code{lt_dlsym}.
+
+The callback will be given @strong{every} module loaded by all the
+libltdl module clients in the current address space, including any
+modules loaded by other libraries such as libltdl itself, and should
+return non-zero if that module does not fulfill the interface
+requirements of your loader.
+
address@hidden
+int
+my_interface_cb (lt_dlhandle handle, const char *id_string)
address@hidden
+  char *(*module_id) (void) = NULL;
+
+  /* @r{A valid my_module must provide all of these symbols.}  */
+  if (!((module_id = (char*(*)(void)) lt_dlsym ("module_version"))
+        && lt_dlsym ("my_module_entrypoint")))
+      return 1;
+
+  if (strcmp (id_string, module_id()) != 0)
+      return 1;
+
+  return 0;
address@hidden
address@hidden example
address@hidden deftp
+
address@hidden lt_dlinterface_id lt_dlinterface_register (@w{const char 
address@hidden,} @w{lt_dlhandle_interface address@hidden)
+Use this function to register your interface validator with libltdl,
+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
address@hidden can be used to filter the module handles
+returned by the iteration functions below.
address@hidden deftypefun
+
address@hidden int lt_dlhandle_map (@w{lt_dlinterface_id @var{iface}}, @w{int 
(address@hidden) (lt_dlhandle @var{handle}, void * @var{data})}, @w{void * 
@var{data}})
+For each module that matches @var{iface}, call the function
address@hidden  When writing the @var{func} callback function, the
+argument @var{handle} is the handle of a loaded modules, and
address@hidden is the @var{data} argument passed to
address@hidden As soon as @var{func} returns a non-zero value
+for one of the handles, @code{lt_dlhandles_map} will stop calling
address@hidden and immediately return 1.  Otherwise 0 is returned.
 @end deftypefun
 
address@hidden lt_dlhandle lt_dlhandle_next (@w{lt_dlhandle place})
-Iterate over the loaded module handles, returning the first handle in the
-list if @var{place} is @code{NULL}, and the next one on subsequent calls.
-If @var{place} is the last element in the list of loaded modules, this
-function returns @code{NULL}.
address@hidden lt_dlhandle lt_dlhandle_iterate (@w{lt_dlinterface_id 
@var{iface}}, @w{lt_dlhandle place})
+Iterate over the module handles loaded by @var{iface}, returning the
+first matching handle in the list if @var{place} is @code{NULL}, and
+the next one on subsequent calls.  If @var{place} is the last element
+in the list of eligible modules, this function returns @code{NULL}.
 
 @example
 lt_dlhandle handle = 0;
+lt_dlinterface_id iface = my_interface_id;
 
-while ((handle = lt_dlhandle_next (handle)))
+while ((handle = lt_dlhandle_iterate (iface, handle)))
   @{
     @dots{}
   @}
 @end example
 @end deftypefun
 
address@hidden lt_dlhandle lt_dlhandle_find (@w{const char address@hidden)
-Search through the loaded module handles for a module named
address@hidden lt_dlhandle lt_dlhandle_fetch (@w{lt_dlinterface_id 
@var{iface}}, @w{const char address@hidden)
+Search through the module handles loaded by @var{iface} for a module named
 @var{module_name}, returning its handle if found or else @code{NULL}
-if no such named module has been loaded.
+if no such named module has been loaded by @var{iface}.
 @end deftypefun
 
 However, you might still need to maintain your own list of loaded
@@ -3771,26 +3821,10 @@ module handles (in parallel with the lis
 if there were any other data that your application wanted to associate
 with each open module.  Instead, you can use the following @sc{api}
 calls to do that for you.  You must first obtain a unique interface id
-from libltdl, and subsequently always use it to retrieve the data you
-stored earlier.  This allows different libraries to each store their
-own data against loaded modules, without interfering with one another.
-
address@hidden {Type} lt_dlinterface_id
-The opaque type used to hold individual data set keys.
address@hidden deftp
-
address@hidden {Type} int lt_dlhandle_interface (@w{lt_dlhandle @var{handle},} 
@w{const char address@hidden)
-Functions of this type are called to check that a handle conforms to a
-library's expected module interface when iterating over the global
-handle list.
address@hidden deftp
-
address@hidden lt_dlinterface_id lt_dlinterface_register (@w{const char 
address@hidden,} @w{lt_dlhandle_interface address@hidden)
-Use this to obtain a unique key to store and retrieve per module data,
-if you supply an @var{id_string} and @var{iface}, then the resulting
address@hidden can be used to filter the module handles
-returned by @samp{lt_dlhandle_next}.
address@hidden deftypefun
+from libltdl as described above, and subsequently always use it to
+retrieve the data you stored earlier.  This allows different libraries
+to each store their own data against loaded modules, without
+interfering with one another.
 
 @deftypefun {void *} lt_dlinterface_set_data (@w{lt_dlinterface_id @var{key}}, 
@w{lt_dlhandle @var{handle}}, @w{void * @var{data}})
 Set @var{data} as the set of data uniquely associated with @var{key} and
@@ -3825,76 +3859,6 @@ Return the address of the data associate
 @var{handle}, or else @code{NULL} if there is none.
 @end deftypefun
 
-The preceding functions can be combined with @code{lt_dlforeach} to
-implement search and apply operations without the need for your
-application to track the modules that have been loaded and unloaded:
-
address@hidden
-int
-my_dlinterface_callback (lt_dlhandle handle, void *key)
address@hidden
-  struct my_module_data *my_data;
-
-  my_data = lt_dlinterface_get_data (handle, (lt_dlinterface_id) key);
-
-  return process (my_data);
address@hidden
-
-int
-my_dlinterface_foreach (lt_dlinterface_id key)
address@hidden
-  lt_dlforeach (my_dlinterface_callback, (void *) key);
address@hidden
address@hidden example
-
address@hidden lt_dlhandle lt_dlhandle_first (@w{lt_dlinterface_id @var{key}})
-Normally, you can fetch each of the loaded module handles in turn with
-successive calls to @samp{lt_dlhandle_next} as shown in the example
-above.  In that example, the loop iterates over every libltdl loaded
-module in your application, including the modules used by libltdl
-itself!  This is useful from within a module loader for example.
-
address@hidden
-Often, your application doesn't want to concern itself with modules
-loaded by the libraries it uses, or for libltdl's internal use.  In
-order to do that, you need to specify an interface validator callback:
-
address@hidden
-/* @r{Return non-zero if} @var{handle} @r{doesn't conform to my iface.}  */
-int
-iface_validator_callback (lt_dlhandle handle, const char *id_string)
address@hidden
-    return (lt_sym (handle, "module_entry_point") != 0)
address@hidden
address@hidden example
-
address@hidden
-When you register for an interface identification key with
address@hidden, you log the interface validator.  But
-this time, when you start the iterator loop over the loaded module
-handles, if you fetch the first handle with @samp{lt_dlhandle_first},
-then that and all subsequent calls to @samp{lt_dlhandle_next} will
-skip any loaded module handles that fail the registered interface
-validator callback function:
-
address@hidden
-/* @r{Register for an} interface_id @r{to identify ourselves to} libltdl.  */
-interface_id = lt_dlinterface_register ("example", iface_validator_callback);
-
address@hidden
-/* @r{Iterate over the modules related to my} interface_id.  */
address@hidden
-  lt_dlhandle handle;
-  for (handle = lt_dlhandle_first (interface_id);
-       handle;
-       handle = lt_dlhandle_next (handle))
-    @{
-      @dots{}
-    @}
address@hidden
address@hidden example
address@hidden deftypefun
-
 Old versions of libltdl also provided a simpler, but similar, @sc{api}
 based around @code{lt_dlcaller_id}.  Unfortunately, it had no
 provision for detecting whether a module belonged to a particular
Index: libtool--devo--1.0/libltdl/ltdl.c
===================================================================
--- libtool--devo--1.0.orig/libltdl/ltdl.c
+++ libtool--devo--1.0/libltdl/ltdl.c
@@ -2113,91 +2113,68 @@ lt_dlgetinfo (lt_dlhandle handle)
 }
 
 
-/* Nasty semantics, necessary for reasonable backwards compatibility:
-   Either iterate over the whole handle list starting with lt_dlhandle_next(0),
-   or else iterate over just the handles of modules that satisfy a given
-   interface by getting the first element using lt_dlhandle_first(iface).  */
-
-static lt__interface_id *iterator = 0;
-
-lt_dlhandle
-lt_dlhandle_first (lt_dlinterface_id iface)
-{
-  iterator = iface;
-
-  return handles;
-}
-
-
 lt_dlhandle
-lt_dlhandle_next (lt_dlhandle place)
+lt_dlhandle_iterate (lt_dlinterface_id iface, lt_dlhandle place)
 {
   lt__handle *handle = (lt__handle *) place;
+  lt__interface_id *iterator = (lt__interface_id *) iface;
+
+  assert (iface); /* iface is a required argument */
 
   if (!handle)
-    {
-      /* old style iteration across all handles */
-      iterator = 0;
-      handle = (lt__handle *) handles;
-    }
-  else
-    {
-      /* otherwise start at the next handle after the passed one */
-      handle = handle->next;
-    }
+    handle = (lt__handle *) handles;
 
-  /* advance until the interface check (if we have one) succeeds */
-  while (handle && iterator && iterator->iface
+  /* advance while the interface check fails */
+  while (handle && iterator->iface
         && ((*iterator->iface) (handle, iterator->id_string) != 0))
     {
       handle = handle->next;
     }
 
-  if (!handle)
-    {
-      /* clear the iterator after the last handle */
-      iterator = 0;
-    }
-
   return (lt_dlhandle) handle;
 }
 
 
 lt_dlhandle
-lt_dlhandle_find (const char *module_name)
+lt_dlhandle_fetch (lt_dlinterface_id iface, const char *module_name)
 {
-  lt__handle *cur = (lt__handle *) handles;
+  lt_dlhandle cur = 0;
+
+  assert (iface); /* iface is a required argument */
 
-  if (cur)
+  while ((cur = lt_dlhandle_iterate (cur, iface)))
     {
-      do
-       {
-         if (cur->info.name && streq (cur->info.name, module_name))
-           break;
-       }
-      while ((cur = cur->next));
+      if (cur && cur->info.name && streq (cur->info.name, module_name))
+       break;
     }
 
   return cur;
 }
 
+
 int
-lt_dlforeach (int (*func) (lt_dlhandle handle, void *data), void *data)
+lt_dlhandle_map (lt_dlinterface_id iface,
+                int (*func) (lt_dlhandle handle, void *data), void *data)
 {
+  lt__interface_id *iterator = (lt__interface_id *) iface;
+  lt__handle *cur = (lt__handle *) handles;
+  lt__handle *tmp = 0;
+  lt__handle *prev = 0;
   int errors = 0;
-  lt__handle *cur;
 
-  cur = (lt__handle *) handles;
-  while (cur)
-    {
-      lt__handle *tmp = cur;
+  assert (iface); /* iface is a required argument */
 
-      cur = cur->next;
-      if ((*func) (tmp, data))
+  while (cur && !errors)
+    {
+      /* advance while the interface check fails */
+      while (cur && iterator->iface
+            && ((*iterator->iface) (cur, iterator->id_string) != 0))
        {
-         ++errors;
-         break;
+         cur = cur->next;
        }
+
+      if ((*func) (cur, data))
+       ++errors;
     }
 
   return errors;
Index: libtool--devo--1.0/libltdl/ltdl.h
===================================================================
--- libtool--devo--1.0.orig/libltdl/ltdl.h
+++ libtool--devo--1.0/libltdl/ltdl.h
@@ -126,10 +126,12 @@ typedef   struct {
 } lt_dlinfo;
 
 LT_SCOPE const lt_dlinfo *lt_dlgetinfo     (lt_dlhandle handle);
-LT_SCOPE lt_dlhandle   lt_dlhandle_first   (lt_dlinterface_id key);
-LT_SCOPE lt_dlhandle   lt_dlhandle_next    (lt_dlhandle place);
-LT_SCOPE lt_dlhandle   lt_dlhandle_find    (const char *module_name);
-LT_SCOPE int           lt_dlforeach        (
+
+LT_SCOPE lt_dlhandle   lt_dlhandle_iterate (lt_dlinterface_id iface,
+                                            lt_dlhandle place);
+LT_SCOPE lt_dlhandle   lt_dlhandle_fetch   (lt_dlinterface_id iface,
+                                            const char *module_name);
+LT_SCOPE int           lt_dlhandle_map     (lt_dlinterface_id iface,
                                int (*func) (lt_dlhandle handle, void *data),
                                void *data);
 
-- 
Gary V. Vaughan      ())_.  address@hidden,gnu.org}
Research Scientist   ( '/   http://tkd.kicks-ass.net
GNU Hacker           / )=   http://www.gnu.org/software/libtool
Technical Author   `(_~)_   http://sources.redhat.com/autobook




reply via email to

[Prev in Thread] Current Thread [Next in Thread]