LOAD-FOREIGN-LIBRARY and USE-FOREIGN-LIBRARY have the undesirable
side-effect of closing the library first before loading it. While
unloading doesn't seem to work on ccl, on Lispworks, mkcl and ecl this
actually does what is intended, but it has unfortunate consequences
with some libraries which perform initializations which are not undone
when they are unloaded. reloading the library is disastrous.

the names LOAD-FOREIGN and USE-FOREIGN have nothing to suggest there
is unloading involved.  The expectation is that unloaded libraries are
loaded. If a library is already loaded there is no expectation that it
will be touched.  This is the desired behaviour.

In my case I have been bitten by USE-FOREIGN-LIBRARY and I changed it
to not unload with the following patch. Can anyone suggest anything
better?

[Please don;t ask me to open a github issue, I've tried using the
github channels since 2019 absolutely no success]

diff --git a/src/libraries.lisp b/src/libraries.lisp
index f39558d..b6437e4 100644
--- a/src/libraries.lisp
+++ b/src/libraries.lisp
@@ -430,6 +430,9 @@ (defun filter-pathname (thing)
     (pathname (namestring thing))
     (t        thing)))
 
+
+(defvar *load-foreign-library-should-not-close-the-library-before-loading-it* nil)
+
 (defun load-foreign-library (library &key search-path)
   "Loads a foreign LIBRARY which can be a symbol denoting a library defined
 through DEFINE-FOREIGN-LIBRARY; a pathname or string in which case we try to
@@ -437,7 +440,13 @@ (defun load-foreign-library (library &key search-path)
 or finally list: either (:or lib1 lib2) or (:framework <framework-name>).
 The option :CANARY can specify a symbol that will be searched to detect if
 the library is already loaded, in which case DEFINE-FOREIGN-LIBRARY will mark
-the library as loaded and return."
+the library as loaded and return.
+
+This always function attempts to close the library before trying to
+open it.  To disable that bind
+*LOAD-FOREIGN-LIBRARY-SHOULD-NOT-CLOSE-THE-LIBRARY-BEFORE-LOADING-IT*
+to T when calling this.
+"
   (let ((library (filter-pathname library)))
     (restart-case
         (progn
@@ -447,8 +456,9 @@ (defun load-foreign-library (library &key search-path)
           ;; counter, and thus thwarting dlclose, then we need to try
           ;; to call CLOSE-FOREIGN-LIBRARY and ignore any signaled
           ;; errors.
-          (ignore-some-conditions (foreign-library-undefined-error)
-            (close-foreign-library library))
+          (unless  *load-foreign-library-should-not-close-the-library-before-loading-it*
+            (ignore-some-conditions (foreign-library-undefined-error)
+              (close-foreign-library library)))
           (%do-load-foreign-library library search-path))
       ;; Offer these restarts that will retry the call to
       ;; %LOAD-FOREIGN-LIBRARY.
@@ -461,7 +471,8 @@ (defun load-foreign-library (library &key search-path)
         (load-foreign-library new-library :search-path search-path)))))
 
 (defmacro use-foreign-library (name)
-  `(load-foreign-library ',name))
+  `(let ((*load-foreign-library-should-not-close-the-library-before-loading-it* t))
+     (load-foreign-library ',name)))
 
 ;;;# Closing Foreign Libraries
 

Reply via email to