[Openmcl-devel] An unfortunate interaction between CFFI and open-shared-library

Ron Garret ron at flownet.com
Sun Sep 19 13:31:39 PDT 2010


Today I tried to load CL-MYSQL which I have done a zillion times before.  To my dismay, it failed with the following error on the altconsole:

> Error: Error opening shared library "libmysqlclient_r.dylib": dlopen(libmysqlclient_r.dylib, 10): image not found
> While executing: (:INTERNAL GUI::|-[LispApplication sendEvent:]|), in process Initial(0).

This despite the fact that I hadn't changed anything since the last time it worked, except for updating CCL itself.

The cause seems to be a recent change in open-shared-library:

(defun open-shared-library (name &optional (process #+darwin-target :initial
                                                    #-darwin-target :current))
  "If the library denoted by name can be loaded by the operating system,
return an object of type SHLIB that describes the library; if the library
is already open, increment a reference count. If the library can't be
loaded, signal a SIMPLE-ERROR which contains an often-cryptic message from
the operating system."
  (if (or (eq process :current)
          (eq process *current-process*)
          (and (eq process :initial)
               (eq *current-process* *initial-process*)))
    (open-shared-library-internal name)
    (call-in-process (lambda () (open-shared-library name))
                     (if (eq process :initial)
                       *initial-process*
                       process))))

It appears that open-shared-library when run on Darwin runs on the main thread rather than the calling thread.  But CFFI wraps this call in a handler-case, which it relies on to find the library:

(defun load-foreign-library-path (name path)
  "Tries to load PATH using %LOAD-FOREIGN-LIBRARY which should try and
find it using the OS's usual methods. If that fails we try to find it
ourselves."
  (handler-case
      (%load-foreign-library name path)
    (error (error)
      (if-let (file (find-file path *foreign-library-directories*))
              (handler-case
                  (%load-foreign-library name (native-namestring file))
                (simple-error (error)
                  (report-simple-error name error)))
              (report-simple-error name error)))))

Now that open-shared-library is running in a different thread it is no longer in the dynamic context of the handler-case, so it dies if it can't find the library on the first try.

So... is there a reason that open-shared-library is dispatching to the initial thread?  If there isn't, it really shouldn't.  And if there is, well, then Houston, we have a problem.

rg




More information about the Openmcl-devel mailing list