-
Notifications
You must be signed in to change notification settings - Fork 76
Description
A mentioned in a previously closed comment section, there is an issue on Apple Silicon where, depending on which other gems are used, ruby-oci8 might crash with a SIGSEGV when initiating the connection to Oracle.
There is a workaround that solves the problem for my particular combination of gems, see the quote below. Also note that I had a test case where I was able to reproduce individual gems creating the problem - but after a later MacOS upgrade, I was not able to get it to run even with no other gems loaded at all (i.e. the issue already happened with the absolut minimum of "stuff" loaded by ruby and bundle themselves).
As mentioned there, I find it very hard to imagine how ruby-oci8 would prevent that problem from happening: the root cause lies squarly on the way the Oracle libraries are built. Neither can ruby-oci8 catch the SIGSEGV (ruby does not allow that), nor can it possibly detect whether some other dylib has already been bound to a function required by the Oracle dylibs. By the time ruby-oci8 is loaded, it might already be too late.
But maybe there is a way to inform the user about this issue in some way? Some gems output warnings or helpful notices like this during the bundle install when they are first downloaded/compiled. Maybe it would make sense to alert the user of this possible issue. Or heck, at the very least place a comment in the code near the line where it happens (oci8.rb:133) though that may be spurious - in theory it could happen with any call into the flat-namespaced Oracle libs.
I found some time to delve into this again. The issue can be worked around by using this command to instruct the MacOS
dyldloader to load one of the Oracle libraries first, guaranteed:export DYLD_INSERT_LIBRARIES=$OCI_DIR/libnnz.dylibThis goes into a
rbenvexec hook like so (if you're usingrbenv):~$ cat .rbenv/rbenv.d/exec/fix_oci8.bash echo "fix_oci8.bash: inserting DYLD_INSERT_LIBRARIES for Oracle" export DYLD_INSERT_LIBRARIES=$OCI_DIR/libnnz.dylibThe script will then always automatically be sourced just before the final, actual
rubyexecutable is invoked. It seems to work even with more convoluted commands likebundle exec rails cucumberwhich go through multiple layers of wrappers...I assume the only way this can really go wrong is if there also is another library that tries to access the same symbols as the Oracle libs and also uses the flat-namespaces model instead of the 2-level variant. But, knock on wood, so far it does seem to work for my particular case.
Alas, I don't see how
ruby-oci8could integrate this as a fix itself - by the timeruby-oci8is invoked, it is too late already, and SIGSEGV cannot be trapped by ruby code.