Link to specific Oracle instant client dynamic library on OS X
Updated:
I mailed with the questioner and the crash disappeared by adding "require 'oci8'" at the top of his application.
According the log outputted by DYLD_PRINT_LIBRARIES=1 and DYLD_PRINT_BINDINGS=1, this issue was caused by function interposition. The libclntsh.dylib and the OS X LDAP library export _ldap_first_entry whose implementation differs. When the OS X LDAP libary is loaded into the process memory before libclntsh.dylib and a function in libclntsh.dylib tries to use _ldap_first_entry in libclntsh.dylib, it faulty uses _ldap_first_entry in the OS X LDAP library.It may happen on Unix (except OS X) generally and on OS X only when a library is linked with flat_namespace.
IMO, he doesn't use the OS X LDAP library explicitly. He uses a kind of authorization module, which depends on the library internally.
The rest is not changed.
I have an idea. But I haven't tested it.
IMO, ruby doesn't use OS X version library directly. A extension library such ruby-ldap uses it. If so, "require 'oci8'" before the extension library may solve the issue.
require 'oci8' # This must be before any other extension libraries using LDAP.require 'ldap' # for example
But it causes another issue. When the ruby-ldap library try to use OS X version _ldap_first_entry, Oracle version _ldap_first_entry is called and the process crashes. You need to customize oci8 to avoid it.
Change DLOPEN_FLAG
in ext/oci8/oci8lib.c as follows,
#define DLOPEN_FLAG (RTLD_NOW|RTLD_LOCAL)
then install as follows
gem build ruby-oci8.gemspecgem install ruby-oci8-2.1.5.gem -- --with-runtime-check
and use it.
require 'oci8' # This must be before any other extension libraries using LDAP.require 'ldap'
RTLD_LOCAL
hides symbols in libclntsh.dylib from other extension libraries.RTLD_NOW
resolves symbols immediately and prevents libclntsh.dylib from using symbols in succeedingly loaded libraries.--with-runtime-check
forces ruby-oci8 to use dlopen().
I hope that OS X dlopen() specification is same with Linux and it works.
You need to use 'otool -L < path to dylib >' to dump the dylibs that your executable or dylibs are dependent on. They should have been built to access the bundle frameworks via a relative path ('@executable_path/../Frameworks/*' (or @loader_path or @rpath)) instead of the system ones.
See the "DYNAMIC LIBRARY LOADING" section of the dyld man page at: https://developer.apple.com/library/mac/#documentation/Darwin/Reference/ManPages/man1/dyld.1.html
The install_path of a dylib is used to tell the execs & dylibs that link against it where they should expect to find it at runtime. You can (try to) change the install_path of a dylib via the install_name_tool command line tool. (I say 'try' because it can fail silently so ALWAYS check afterwords to see if it actually worked.)