2000-12-01 Gary V. Vaughan * 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. Index: doc/libtool.texi =================================================================== RCS file: /home/cvs/libtool/doc/libtool.texi,v retrieving revision 1.109 diff -u -p -r1.109 libtool.texi --- doc/libtool.texi 2000/11/21 08:53:33 1.109 +++ doc/libtool.texi 2000/12/02 01:33:04 @@ -2846,6 +2846,23 @@ directories. Return 0 on success. Return the current user-defined library search path. @end deftypefun address@hidden 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. address@hidden deftypefun + address@hidden 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 address@hidden address@hidden 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: libltdl/ltdl.c =================================================================== RCS file: /home/cvs/libtool/libltdl/ltdl.c,v retrieving revision 1.115 diff -u -p -r1.115 ltdl.c --- libltdl/ltdl.c 2000/11/29 22:59:56 1.115 +++ libltdl/ltdl.c 2000/12/02 01:33:09 @@ -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)) { @@ -1630,7 +1648,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; @@ -1712,6 +1735,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); @@ -2012,7 +2038,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; @@ -2131,7 +2157,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; @@ -2163,6 +2193,12 @@ lt_dlclose (handle) return error; } + if (LT_DLIS_RESIDENT (handle)) + { + last_error = LT_DLSTRERROR (CLOSE_RESIDENT_MODULE); + return 1; + } + return 0; } @@ -2343,6 +2379,34 @@ const char * 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 * Index: libltdl/ltdl.h =================================================================== RCS file: /home/cvs/libtool/libltdl/ltdl.h,v retrieving revision 1.48 diff -u -p -r1.48 ltdl.h --- libltdl/ltdl.h 2000/11/29 22:59:56 1.48 +++ libltdl/ltdl.h 2000/12/02 01:33:11 @@ -159,6 +159,10 @@ extern lt_ptr lt_dlsym LT_PARAMS((l 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_PARAM 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 {