[cmucl-imp] ignore-errors for missing foreign functions

Anton Vodonosov avodonosov at yandex.ru
Mon Jan 28 03:41:32 UTC 2019


The background of this question is difficulty in cl+ssl support, because OpenSSL constantly add / remove functions, so different versions of libssl library provide different sets of functions. Even the function to test OpenSSL version nubmer was renamed. Previously it was called SSLeay, in newer versions it's called OpenSSL_version_num.

If found that unlike cffi:defcfun, cffi:foreign-funcall can be wrapped into ignore-case or IF.

    (when nil
      (cffi:foreign-funcall "OpenSSL_version_num" :long))

A fasl with such code loads without an error.

But when I try to wrap that into a defun:

    #-cmucl                                                                                              
    (cffi:defcfun ("OpenSSL_version_num" openssl-version-num)                                            
        :long)
    #+cmucl
    (defun openssl-version-num ()
      (cffi:foreign-funcall "OpenSSL_version_num" :long))

It fails again during fasl load:

Undefined foreign symbol: "OpenSSL_version_num"
   [Condition of type KERNEL:SIMPLE-PROGRAM-ERROR]

Restarts:
 0: [CONTINUE] Return NIL from load of "/home/testgrid/cl+ssl/cl-plus-ssl/test/run-on-many-lisps-and-openssls/test-cmucl".
 1: [RETRY] Retry SLIME interactive evaluation request.
 2: [*ABORT] Return to SLIME's top level.
 3: [ABORT] Return to Top-Level.

Backtrace:
  0: (KERNEL:UNDEFINED-FOREIGN-SYMBOL-ERROR-HANDLER "<error finding name>" #.(SYSTEM:INT-SAP #x3FFFB910) #<Alien (* SYSTEM:SYSTEM-AREA-POINTER) at #x3FFFB61C> (16))
  1: (KERNEL::INTERNAL-ERROR #.(SYSTEM:INT-SAP #x3FFFB61C) #<unused-arg>)
  2: ("call_into_lisp+#xAB [#x8054FEF] /home/testgrid/lisps/cmucl-2013-04/bin/lisp")
  3: ("funcall2+#x2C [#x8054ABC] /home/testgrid/lisps/cmucl-2013-04/bin/lisp")
  4: ("interrupt_internal_error+#x7A [#x8051C7A] /home/testgrid/lisps/cmucl-2013-04/bin/lisp")
  5: ("sigtrap_handler+#x183 [#x8054DD3] /home/testgrid/lisps/cmucl-2013-04/bin/lisp")
  6: ("__kernel_rt_sigreturn+#x0 [#xB7FE1410] ")
  7: ("os_link_one_symbol+#xCB [#x80553CB] /home/testgrid/lisps/cmucl-2013-04/bin/lisp")
  8: (LISP::ADD-FOREIGN-LINKAGE "OpenSSL_version_num" :CODE #("resolve_linkage_tramp" 1 NIL "alloc_overflow_sse2" 1 ...) #<HASH-TABLE :TEST EQUAL :WEAK-P NIL :COUNT 205 {28120A85}> ...)
  9: (LISP::FOREIGN-SYMBOL-ADDRESS-AUX "OpenSSL_version_num" :CODE)
 10: (LISP::FOP-FOREIGN-FIXUP)
 11: (LISP::LOAD-GROUP #<Stream for file "/home/testgrid/cl+ssl/cl-plus-ssl/test/run-on-many-lisps-and-openssls/test-cmucl.sse2f">)
 12: (LISP::FASLOAD #<Stream for file "/home/testgrid/cl+ssl/cl-plus-ssl/test/run-on-many-lisps-and-openssls/test-cmucl.sse2f">)
 13: (LISP::INTERNAL-LOAD #P"/home/testgrid/cl+ssl/cl-plus-ssl/test/run-on-many-lisps-and-openssls/test-cmucl.sse2f" ..)
 14: (LOAD "/home/testgrid/cl+ssl/cl-plus-ssl/test/run-on-many-lisps-and-openssls/test-cmucl" :VERBOSE NIL :PRINT ...)
 15: ("DEFSLIMEFUN INTERACTIVE-EVAL")
 16: (SWANK::CALL-WITH-RETRY-RESTART "Retry SLIME interactive evaluation request." #<Closure Over Function "DEFSLIMEFUN INTERACTIVE-EVAL" {5914C431}>)
 17: (SWANK::CALL-WITH-BUFFER-SYNTAX NIL #<Closure Over Function "DEFSLIMEFUN INTERACTIVE-EVAL" {5914C421}>)
 18: (SWANK:EVAL-FOR-EMACS (SWANK:INTERACTIVE-EVAL "(load \"/home/testgrid/cl+ssl/cl-plus-ssl/test/run-on-many-lisps-and-openssls/test-cmucl\")") "COMMON-LISP-USER" 90)
 19: (SWANK::PROCESS-REQUESTS T)
 20: ("DEFUN HANDLE-REQUESTS")
 21: ("DEFUN HANDLE-REQUESTS")
 22: ("DEFINTERFACE CALL-WITH-DEBUGGER-HOOK" #<Function SWANK:SWANK-DEBUGGER-HOOK {58B4DA89}> #<Closure Over Function "DEFUN HANDLE-REQUESTS" {5914A8C1}>)


So, it's difficult to write CMUCL FFI code for a library whose API changes from version to version. Maybe it can be solved by placing OpenSSL_version_num and SSLeay declarations into different files, then compile and load the fasls myself, instead of ASDF. And depending on which of the fals fails we will know what function is available. Then place all other functions which are present not in all versions into separate files, and use the :if-feature ASDF's facility to load them conditionally.

But that's a lot of code restructuring and effort. Is there a simpler alternative?

Best regards,
- Anton




More information about the cmucl-imp mailing list