]> git.ipfire.org Git - thirdparty/libtool.git/commitdiff
* doc/libtool.texi (Libltdl interface): Add documentation.
authorGary V. Vaughan <gary@gnu.org>
Sat, 16 Dec 2000 03:19:09 +0000 (03:19 +0000)
committerGary V. Vaughan <gary@gnu.org>
Sat, 16 Dec 2000 03:19:09 +0000 (03:19 +0000)
* libltdl/ltdl.h (lt_dlmakeresident, lt_dlisresident):  Add
prototypes.
(LT_DLERROR_CLOSE_RESIDENT_MODULE): New error status.
* libltdl/ltdl.c (lt_dlmakeresident, lt_dlisresident):  Allow
making and testing of resident module status, which prevents a
module from being lt_dlclosed.
(lt_dlopen):  If lt_dlopen()ing self, make the module resident.
(lt_dlclose):  Return an error if the module is resident.

ChangeLog
doc/libtool.texi
libltdl/ltdl.c
libltdl/ltdl.h

index 28fbb0e55a027b0822b677676639b5c3e1e7a879..47404f345d89b5c66a022f6cb24f7ad96cc3d660 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+2000-12-16  Gary V. Vaughan  <gvv@techie.com>
+
+       * doc/libtool.texi (Libltdl interface):  Add documentation.
+       * libltdl/ltdl.h (lt_dlmakeresident, lt_dlisresident):  Add
+       prototypes.
+       (LT_DLERROR_CLOSE_RESIDENT_MODULE): New error status.
+       * libltdl/ltdl.c (lt_dlmakeresident, lt_dlisresident):  Allow
+       making and testing of resident module status, which prevents a
+       module from being lt_dlclosed.
+       (lt_dlopen):  If lt_dlopen()ing self, make the module resident.
+       (lt_dlclose):  Return an error if the module is resident.
 2000-12-16  Nick Hudson  <skrll@netbsd.org>
 
        * ltconfig.in (netbsd*, deplibs_check_method): Enable ILD support
index b78766a2fcd6ccd046747504f4739a0f8f8d197a..4c222cadc301f3a61983916ae8c98571df0f2925 100644 (file)
@@ -3028,6 +3028,23 @@ directories.  Return 0 on success.
 Return the current user-defined library search path.
 @end deftypefun
 
+@deftypefun int lt_dlmakeresident (lt_dlhandle @var{handle})
+Mark a module so that it cannot be @samp{lt_dlclose}d.  This can be
+useful if a module implements some core functionality in your project,
+which would cause your code to crash if removed.  Return 0 on success.
+
+If you use @samp{lt_dlopen (NULL)} to get a @var{handle} for the running
+binary, that handle will always be marked as resident, and consequently
+cannot be successfully @samp{lt_dlclose}d.
+@end deftypefun
+
+@deftypefun int lt_dlisresident (lt_dlhandle @var{handle})
+Check whether a particular module has been marked as resident, returning 1
+if it has or 0 otherwise.  If there is an error while executing this
+function, return -1 and set an error message for retrieval with
+@code{lt_dlerror}.
+@end deftypefun
+
 @deftypefun {const lt_dlinfo *}lt_dlgetinfo (lt_dlhandle @var{handle})
 Return a pointer to a struct that contains some information about
 the module @var{handle}.  The contents of the struct must not be modified.
index 57e0dd214e3fd4c17cc2f45017ae7e71c4b11883..dbf4de152fe91809427b3a52f8680a2b4afb9993 100644 (file)
@@ -122,8 +122,20 @@ struct lt_dlhandle_struct {
   lt_dlhandle         *deplibs;        /* dependencies */
   lt_module            module;         /* system module handle */
   lt_ptr               system;         /* system specific data */
+  int                  flags;          /* various boolean stats */
 };
 
+/* Various boolean flags can be stored in the flags field of an
+   lt_dlhandle_struct... */
+#define LT_DLGET_FLAG(handle, flag) ((handle)->flags&(flag) == (flag))
+#define LT_DLSET_FLAG(handle, flag) ((handle)->flags |= (flag))
+
+#define LT_DLRESIDENT_FLAG         (0x01 << 0)
+/* ...add more flags here... */
+
+#define LT_DLIS_RESIDENT(handle)    LT_DLGET_FLAG(handle, LT_DLRESIDENT_FLAG)
+
+
 static const char      objdir[]                = LTDL_OBJDIR;
 #ifdef LTDL_SHLIB_EXT
 static const char      shlib_ext[]             = LTDL_SHLIB_EXT;
@@ -1089,15 +1101,21 @@ lt_dlexit ()
     {
       int      level;
 
+      while (handles && LT_DLIS_RESIDENT (handles))
+       {
+         handles = handles->next;
+       }
+
       /* close all modules */
       for (level = 1; handles; ++level)
        {
          lt_dlhandle cur = handles;
+
          while (cur)
            {
              lt_dlhandle tmp = cur;
              cur = cur->next;
-             if (tmp->info.ref_count <= level)
+             if (!LT_DLIS_RESIDENT (cur) && tmp->info.ref_count <= level)
                {
                  if (lt_dlclose (tmp))
                    {
@@ -1631,7 +1649,12 @@ unload_deplibs(handle)
   if (handle->depcount)
     {
       for (i = 0; i < handle->depcount; ++i)
-       errors += lt_dlclose (handle->deplibs[i]);
+       {
+         if (!LT_DLIS_RESIDENT (handle->deplibs[i]))
+           {
+             errors += lt_dlclose (handle->deplibs[i]);
+           }
+       }
     }
 
   return errors;
@@ -1713,6 +1736,9 @@ lt_dlopen (filename)
       handle->deplibs          = 0;
       newhandle                        = handle;
 
+      /* lt_dlclose()ing yourself is very bad!  Disallow it.  */
+      LT_DLSET_FLAG (handle, LT_DLRESIDENT_FLAG);
+
       if (tryall_dlopen (&newhandle, 0) != 0)
        {
          lt_dlfree(handle);
@@ -2013,7 +2039,7 @@ lt_dlopen (filename)
       handle = newhandle;
     }
 
-  if (!handle->info.ref_count)
+  if (handle->info.ref_count == 0)
     {
       handle->info.ref_count   = 1;
       handle->info.name                = name;
@@ -2132,7 +2158,11 @@ lt_dlclose (handle)
 
   handle->info.ref_count--;
 
-  if (!handle->info.ref_count)
+  /* Note that even with resident modules, we must track the ref_count
+     correctly incase the user decides to reset the residency flag
+     later (even though the API makes no provision for that at the
+     moment).  */
+  if (handle->info.ref_count <= 0 && !LT_DLIS_RESIDENT (handle))
     {
       int      error;
       lt_user_data data = handle->loader->dlloader_data;
@@ -2164,6 +2194,12 @@ lt_dlclose (handle)
       return error;
     }
 
+  if (LT_DLIS_RESIDENT (handle))
+    {
+      last_error = LT_DLSTRERROR (CLOSE_RESIDENT_MODULE);
+      return 1;
+    }
+      
   return 0;
 }
 
@@ -2346,6 +2382,34 @@ lt_dlgetsearchpath ()
   return user_search_path;
 }
 
+int
+lt_dlmakeresident (handle)
+     lt_dlhandle handle;
+{
+  if (!handle)
+    {
+      last_error = LT_DLSTRERROR (INVALID_HANDLE);
+      return -1;
+    }
+
+  LT_DLSET_FLAG (handle, LT_DLRESIDENT_FLAG);
+
+  return 0;
+}
+
+int
+lt_dlisresident        (handle)
+     lt_dlhandle handle;
+{
+  if (!handle)
+    {
+      last_error = LT_DLSTRERROR (INVALID_HANDLE);
+      return -1;
+    }
+
+  return LT_DLIS_RESIDENT (handle);
+}
+
 const lt_dlinfo *
 lt_dlgetinfo (handle)
      lt_dlhandle handle;
index 1ae64bb45a9c083563312d70a3b4e18a7edd70ca..60434cf76acffef928efd629e8aeb15eef87c127 100644 (file)
@@ -159,6 +159,10 @@ extern     lt_ptr      lt_dlsym            LT_PARAMS((lt_dlhandle handle,
 extern const char *lt_dlerror          LT_PARAMS((void));
 extern int         lt_dlclose          LT_PARAMS((lt_dlhandle handle));
 
+/* Module residency management. */
+extern int         lt_dlmakeresident   LT_PARAMS((lt_dlhandle handle));
+extern int         lt_dlisresident     LT_PARAMS((lt_dlhandle handle));
+
 /* Pointers to memory management functions to be used by libltdl. */
 LT_SCOPE  lt_ptr   (*lt_dlmalloc)      LT_PARAMS((size_t size));
 LT_SCOPE  void    (*lt_dlfree)         LT_PARAMS((lt_ptr ptr));
@@ -269,7 +273,8 @@ extern      int             lt_dlloader_remove  LT_PARAMS((
     LT_ERROR(INVALID_HANDLE,       "invalid module handle")            \
     LT_ERROR(BUFFER_OVERFLOW,      "internal buffer overflow")         \
     LT_ERROR(INVALID_ERRORCODE,     "invalid errorcode")               \
-    LT_ERROR(SHUTDOWN,             "library already shutdown")
+    LT_ERROR(SHUTDOWN,             "library already shutdown")         \
+    LT_ERROR(CLOSE_RESIDENT_MODULE, "can't close resident module")
 
 /* Enumerate the symbolic error names. */
 enum {