Rails:调用fork()时可能正在另一个线程中

Cod*_*ang 9 ruby-on-rails

升级到OS10.14后,使用时出现此错误 Httparty

    response = HTTParty.get('http://api.stackexchange.com/2.2/questions?site=stackoverflow')
objc[4182]: +[__NSPlaceholderDictionary initialize] may have been in progress in another thread when fork() was called.
objc[4182]: +[__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.
Run Code Online (Sandbox Code Playgroud)

export OBJC_DISABLE_INITIALIZE_FORK_SAFETY=YES在启动Rails控制台之前,我已经尝试 过了。

但这没有用。

小智 39

Ruby 错误跟踪系统上有一个关于此问题的线程!

https://bugs.ruby-lang.org/issues/14009

基本上......正如您可能已经知道的那样,在多线程环境中分叉(但没有执行)本质上是危险的,必须仔细编写环境以支持这样的事情。Apple 的 Objective-C 库传统上根本不支持在分叉(但不是 exec'd)子进程中调用,但自 High Sierra 10.13 以来,他们试图为此添加有限的支持。然而,在这样做的过程中,他们还定义了分叉后不允许的规则。规则之一是不允许在fork后调用某些Objective-C类的初始化函数;这可能只发生在分叉之前。

到目前为止是有道理的。出现问题的原因是三件事的组合:

Ruby 本身没有链接到任何Objective-C 库,因此它本身不会初始化Objective-C 类。用户可以使用链接到 Objective-C 库的 gem。由于这些 gem 的使用方式,这些 gem 可能会在应用服务器分叉后调用 Objective-C 初始值设定项。新的 Apple 强制规则检查然后中止该过程并显示如下警告:

objc[81924]: +[__NSPlaceholderDictionary initialize] may have been in progress in another thread when fork() was called.
objc[81924]: +[__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.
Run Code Online (Sandbox Code Playgroud)

就其本身而言,Apple 的错误检查是有道理的。分叉是危险的。但所有这些因素加在一起就没有意义了。在 Ruby 中添加一个解决方法(以确保在分叉之前调用 Objective-C 初始化程序的形式)至少将确保我们返回到 High Sierra 之前的行为。

线程中有很多解决方案,您将需要特定于您的环境/已安装 gem 的解决方案。

对我有用的是 export DISABLE_SPRING=true

  • `export DISABLE_SPRING=true` 对我有用。谢谢! (13认同)

小智 16

在Rails控制台之前运行替代方法命令还不够。

以下解决方案对我有用(按照此说明进行操作):

如果遇到此错误,可以将以下代码添加到位于主目录中的.bash_profile中,以解决此问题。

export OBJC_DISABLE_INITIALIZE_FORK_SAFETY=YES
Run Code Online (Sandbox Code Playgroud)
  1. 打开你的终端
  2. 通过输入cd导航到主目录
  3. 在编辑器中打开.bash_profile(VS代码,Atom原子,vim,nano等)。nano .bash_profile
  4. 在文件中复制并粘贴导出OBJC_DISABLE_INITIALIZE_FORK_SAFETY = YES(确保它位于文件底部RVM部分的上方!)

*这很重要* 在我的情况下,进入.bash_profile的过程是这样的:

export OBJC_DISABLE_INITIALIZE_FORK_SAFETY=YES

[[ -s "$HOME/.rvm/scripts/rvm" ]] && source "$HOME/.rvm/scripts/rvm" # Load RVM$
Run Code Online (Sandbox Code Playgroud)

保存文件并退出所有编辑器和终端会话。重新打开您的编辑器,一切现在应该正常工作。

我在此链接Kody Clemens个人博客中找到了该解决方案

  • 当我尝试为 Rails 运行 Spring 命令时,这个问题开始随机发生。将此导出添加到我的“.zshrc”文件的顶部帮助了我——谢谢! (3认同)
  • 另外,进行此更改后重新启动终端。 (2认同)
  • 这看起来不像是一个解决方案,而是一个黑客解决方法,因为——虽然它使错误消失——但它并没有解决根本原因并且[破坏了分叉安全保证](http://sealiesoftware.com/博客/archive/2017/6/5/Objective-C_and_fork_in_macOS_1013.html)。在执行“brew升级”后运行“rails db:migrate:status”时,我遇到了同样的问题,更新了我的所有软件包,包括“gcc”。我还没有解决办法。 (2认同)

Pre*_*rem 6

我在OS Mojave和Windows上遇到此问题ruby-2.4.0。我通过升级到使其工作ruby-2.4.4。我也在这里发布了答案。具有gem ruby​​-oci8的Oracle Instant Client无法与Rails中的DB连接

  • 就简洁性和良好实践而言,这可以说是更好的解决方案。 (2认同)
  • 升级到最新版本 2.5 对我来说没有任何影响。 (2认同)

Jer*_*nch 6

简单地在终端中运行它:

export DISABLE_SPRING=true
Run Code Online (Sandbox Code Playgroud)

或者为了永久修复,请将以上内容添加到~/.zshrc