Ruby
LDAP
macOSHighSierra
ruby-ldap

macOS High Sierra で ruby-ldap を使った Rails アプリがコケるようになった(解決)

ruby 2.4.3 が出たので手元の rails アプリを順次テストしていたところ、 ActiveLdap を使っているアプリで以下のエラーが出てテストができなかった。

$ bin/rake test
Running via Spring preloader in process 84428
Loaded suite rake
Started
objc[84428]: +[__NSPlaceholderDictionary initialize] may have been in progress in another thread when fork() was called.
objc[84428]: +[__NSPlaceholderDictionary initialize] may have been in progress in another thread when fork() was called. We cannot safely call it or ignore it in the fork() child process. Crashing instead. Set a breakpoint on objc_initializeAfterForkError to debug.

エラーメッセージで検索したところ Why Ruby app servers break on macOS High Sierra and what can be done about it を見つけた。そこから macOS High Sierra and “fork” compatibilityに行き着いた。

この修正 が trunk には取り込まれているはずなのに、なぜか 2.4.3 には取り込まれていないため、私の環境では今回の 2.4.3 のアップデート後に問題に遭遇した模様…

どうしたものかと思いつつ検索していたら ruby-buildはパッチを当ててビルドができるを見つけたので、以下のパッチを準備。

--- configure.in.org    2017-12-16 01:51:14.000000000 +0900
+++ configure.in    2017-12-16 01:51:30.000000000 +0900
@@ -4144,8 +4144,8 @@
    ],
     [darwin*], [
    RUBY_APPEND_OPTION(CFLAGS, -pipe)
-   RUBY_APPEND_OPTION(XLDFLAGS, [-framework CoreFoundation])
-   RUBY_APPEND_OPTION(LIBRUBYARG_STATIC, [-framework CoreFoundation])
+   RUBY_APPEND_OPTION(XLDFLAGS, [-framework Foundation])
+   RUBY_APPEND_OPTION(LIBRUBYARG_STATIC, [-framework Foundation])
    ],
     [osf*], [
    if test "$GCC" != "yes" ; then

そして以下のコマンドでパッチを当てた ruby 2.4.3 をビルド & インストール。

$ cat diff.configure | rbenv install --patch 2.4.3

そして再度、テストしてみると…

$ bin/rake test
Running via Spring preloader in process 84428
Loaded suite rake
Started
objc[84428]: +[__NSPlaceholderDictionary initialize] may have been in progress in another thread when fork() was called.
objc[84428]: +[__NSPlaceholderDictionary initialize] may have been in progress in another thread when fork() was called. We cannot safely call it or ignore it in the fork() child process. Crashing instead. Set a breakpoint on objc_initializeAfterForkError to debug.

ダメだよ orz。

ということは native build が必要な ruby-ldap の問題だろうと当てを付け、Gemfile を以下のように修正

(省略)
# ActiveLdap
gem 'activeldap', '~> 4.0.6', :require => 'active_ldap/railtie'
if RUBY_PLATFORM=~ /darwin/
  gem 'net-ldap'
else
  gem 'ruby-ldap'
end
(省略)

bin/bundle 実行後に改めてテストを実施。

$ bin/rake test
Running via Spring preloader in process 85368
Loaded suite rake
Started
....................................................................................................
....................................................................................................
......................................................................................

Finished in 493.189258 seconds.
----------------------------------------------------------------------------------------------------
286 tests, 1424 assertions, 0 failures, 0 errors, 0 pendings, 0 omissions, 0 notifications
100% passed
----------------------------------------------------------------------------------------------------
0.58 tests/s, 2.89 assertions/s
Coverage report generated for Unit Tests to /Users/hiroyuki/Desktop/Work/KaguRa/coverage. 1250 / 1278 LOC (97.81%) covered.

とりあえずはコレでよし。時間があれば ruby-ldap の方も調査して、フィードバックしたい…