2000-12-01 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.
+
* libtool.m4 (_LT_AC_LTCONFIG_HACK): Move the tests for dlopen
from here...
- (AC_LTDL_DLOPEN_SELF): ...to here.
- (_LTDL_AC_CHECK_DLFCN): Factor out repeated code for dlfcn.h
+ (AC_LIBTOOL_DLOPEN_SELF): ...to here.
+ (_LT_AC_CHECK_DLFCN): Factor out repeated code for dlfcn.h
(_LT_AC_TRY_DLOPEN_SELF): Factor out repeated code for
checking dlopen status.
- * ltdl.m4 (AC_LIB_LTDL): Use _LTDL_AC_CHECK_DLFCN.
- dlopen compile time checking. Use _LTDL_AC_CHECK_DLFCN.
- (AC_LTDL_DLSYM_USCORE): Use _LTDL_AC_TRY_DLOPEN_SELF.
+ * ltdl.m4 (AC_LIB_LTDL): Use _LT_AC_CHECK_DLFCN.
+ dlopen compile time checking. Use _LT_AC_CHECK_DLFCN.
+ (AC_LTDL_DLSYM_USCORE): Use _LT_AC_TRY_DLOPEN_SELF.
2000-11-29 Gary V. Vaughan <gvv@techie.com>
* Maybe implement full support for other orthogonal library types
(libhello_g, libhello_p, 64 vs 32-bit ABI's, etc). Make these types
configurable.
+
+* Perhaps the iuse of libltdl could be made cleaner by allowing
+registration of hook functions to call at various points. This would
+hopefully free the user from having to maintain a parallel module
+list with user data. This would likely involve being able to carry
+additional per user module data in the lt_dlmodule structure -- perhaps
+in the form of an associative array keyed by user name?
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 be 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.
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;
{
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))
{
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;
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);
handle = newhandle;
}
- if (!handle->info.ref_count)
+ if (handle->info.ref_count == 0)
{
handle->info.ref_count = 1;
handle->info.name = name;
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;
return error;
}
+ if (LT_DLIS_RESIDENT (handle))
+ {
+ last_error = LT_DLSTRERROR (CLOSE_RESIDENT_MODULE);
+ return 1;
+ }
+
return 0;
}
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;
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));
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 {