如何消除Rails中'actor already terminated (Celluloid::DeadActorError)'警告
问题场景
使用Ctrl + C停止Rails开发服务器时,出现actor already terminated (Celluloid::DeadActorError)警告。环境配置:
- Rails版本:6.1.7
- Ruby版本:3.2.2
- Puma版本:5.6.7
- 当前启用
config.file_watcher = ActiveSupport::EventedFileUpdateChecker作为文件监视器
注释掉config/environments/development.rb中的config.file_watcher = ActiveSupport::EventedFileUpdateChecker可消除警告,但此方法会降级到轮询式文件检查,不推荐长期使用。
错误堆栈
=> Run `bin/rails server --help` for more startup options Puma starting in single mode... * Puma version: 5.6.7 (ruby 3.2.2-p53) ("Birdie's Version") * Min threads: 0 * Max threads: 5 * Environment: development * PID: 12486 * Listening on http://127.0.0.1:3000 * Listening on http://[::1]:3000 Use Ctrl-C to stop ^C- Gracefully stopping, waiting for requests to finish === puma shutdown: 2023-11-07 15:39:16 +0530 === - Goodbye! Exiting bin/rails: warning: Exception in finalizer #<Proc:0x00007f905e3741f0 /home/xxxx/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/activesupport-6.1.7/lib/active_support/evented_file_update_checker.rb:93> /home/xxxx/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/celluloid-0.16.0/lib/celluloid/proxies/actor_proxy.rb:34:in `terminate!': actor already terminated (Celluloid::DeadActorError) from /home/xxxx/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/celluloid-0.16.0/lib/celluloid/proxies/actor_proxy.rb:27:in `terminate' from /home/xxxx/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/celluloid-0.16.0/lib/celluloid/proxies/cell_proxy.rb:60:in `terminate' from /home/xxxx/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/listen-2.10.1/lib/listen/listener.rb:76:in `block in <class:Listener>' from /home/xxxx/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/celluloid-0.16.0/lib/celluloid/fsm.rb:175:in `instance_eval' from /home/xxxx/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/celluloid-0.16.0/lib/celluloid/fsm.rb:175:in `call' from /home/xxxx/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/celluloid-0.16.0/lib/celluloid/fsm.rb:127:in `transition_with_callbacks!' from /home/xxxx/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/celluloid-0.16.0/lib/celluloid/fsm.rb:95:in `transition' from /home/xxxx/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/listen-2.10.1/lib/listen/listener.rb:108:in `stop' from /home/xxxx/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/activesupport-6.1.7/lib/active_support/evented_file_update_checker.rb:113:in `stop' from /home/xxxx/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/activesupport-6.1.7/lib/active_support/evented_file_update_checker.rb:94:in `block in finalizer' bin/rails: warning: Exception in finalizer #<Proc:0x00007f90617787d0 /home/xxxx/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/activesupport-6.1.7/lib/active_support/evented_file_update_checker.rb:93> /home/xxxx/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/celluloid-0.16.0/lib/celluloid/proxies/actor_proxy.rb:34:in `terminate!': actor already terminated (Celluloid::DeadActorError) from /home/xxxx/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/celluloid-0.16.0/lib/celluloid/proxies/actor_proxy.rb:27:in `terminate' from /home/xxxx/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/celluloid-0.16.0/lib/celluloid/proxies/cell_proxy.rb:60:in `terminate' from /home/xxxx/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/listen-2.10.1/lib/listen/listener.rb:76:in `block in <class:Listener>' from /home/xxxx/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/celluloid-0.16.0/lib/celluloid/fsm.rb:175:in `instance_eval' from /home/xxxx/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/celluloid-0.16.0/lib/celluloid/fsm.rb:175:in `call' from /home/xxxx/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/celluloid-0.16.0/lib/celluloid/fsm.rb:127:in `transition_with_callbacks!' from /home/xxxx/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/celluloid-0.16.0/lib/celluloid/fsm.rb:95:in `transition' from /home/xxxx/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/listen-2.10.1/lib/listen/listener.rb:108:in `stop' from /home/xxxx/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/activesupport-6.1.7/lib/active_support/evented_file_update_checker.rb:113:in `stop' from /home/xxxx/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/activesupport-6.1.7/lib/active_support/evented_file_update_checker.rb:94:in `block in finalizer'
原因分析
警告源于ActiveSupport::EventedFileUpdateChecker依赖的旧版本listen gem(2.10.1)与celluloid 0.16.0在Ruby 3.2+下的终止逻辑冲突。Ruby 3.2调整了finalizer执行时机,导致监听器的actor被重复调用terminate方法,触发DeadActorError。
解决方案
1. 更新listen gem(推荐)
Rails 6.1.x兼容listen 3.x版本,该版本已移除对celluloid的依赖,从根源解决冲突:
- 在Gemfile中添加或修改:
gem 'listen', '~> 3.7' - 执行更新命令:
bundle update listen
2. 修补EventedFileUpdateChecker的终止逻辑(临时方案)
如果暂时无法更新gem,可修改active_support/evented_file_update_checker.rb的finalizer代码,捕获DeadActorError避免警告:
- 找到本地gem对应文件(路径示例:
~/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/activesupport-6.1.7/lib/active_support/evented_file_update_checker.rb) - 修改
finalizer方法:def finalizer proc do stop rescue Celluloid::DeadActorError end end
注意:修改本地gem文件会在gem更新后失效,建议使用patch gem持久化补丁。
3. 降级文件监视器(不推荐)
注释掉config/environments/development.rb中的以下配置:
# config.file_watcher = ActiveSupport::EventedFileUpdateChecker
此方法会 fallback到轮询式的ActiveSupport::FileUpdateChecker,虽能消除警告,但文件变更检测效率会降低。
内容的提问来源于stack exchange,提问作者suyogb

