New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Segfault when getting thread-local variable #2566
Comments
Update: after git bisecting puma, it looks like the issue is with this commit: b6ca443. |
@kddeisz I need to look at it more and check the test suite, but the fix might be changing the two instances of the following in cluster.rb: Thread.list.reject { |t| t.thread_variable_get(:fork_safe) } to Thread.list.reject { |t| t.thread_variable?(:fork_safe) && t.thread_variable_get(:fork_safe) } Once the app preloads, there may be threads without the variable. Regardless, Ruby shouldn't be SEGV'ing... |
@MSP-Greg unfortunately that didn't fix it. It looks like it's a specific thread though every time, it's always |
Okay, @MSP-Greg for some reason this fixes it: diff --git a/lib/puma/cluster.rb b/lib/puma/cluster.rb
index c2eff7da..c7247022 100644
--- a/lib/puma/cluster.rb
+++ b/lib/puma/cluster.rb
@@ -333,13 +333,13 @@ module Puma
# Threads explicitly marked as fork safe will be ignored.
# Used in Rails, but may be used by anyone.
- before = Thread.list.reject { |t| t.thread_variable_get(:fork_safe) }
+ before = Thread.list.reject { |t| !t.is_a?(Process::Waiter) && t.thread_variable_get(:fork_safe) }
if preload?
log "* Preloading application"
load_and_bind
- after = Thread.list.reject { |t| t.thread_variable_get(:fork_safe) }
+ after = Thread.list.reject { |t| !t.is_a?(Process::Waiter) && t.thread_variable_get(:fork_safe) }
if after.size > before.size
threads = (after - before) |
Yeah this segfaults in 2.6.6, but works in 2.7.1: if pid = fork
Process.detach(pid)
puts "PARENT!!! #{Thread.list.map { |t| t.thread_variable_get(:foo) }}"
else
puts "CHILD!!!"
end |
I think maybe ruby/ruby@cadfaac#diff-161b2a279f4c67a1ab075a7890ecf6f3f1d483d910910fa52b3715e25cfdcbd7 fixed this? |
See https://bugs.ruby-lang.org/issues/10231. Sorry, I'm intermittently AFK |
When you're trying to access a thread-local variable on Ruby < 2.7, and you call `thread_variable_get` on a `Process::Waiter` (a subclass of `Thread`), it will segfault. This adds a check for which Ruby version you're on to make it safe for Ruby 2.6. Fixes #2566.
When you're trying to access a thread-local variable on Ruby < 2.7, and you call `thread_variable_get` on a `Process::Waiter` (a subclass of `Thread`), it will segfault. This adds a check for which Ruby version you're on to make it safe for Ruby 2.6. Fixes puma#2566.
tl;dr: segfault, puma 5.2.2, ruby 2.6.6p146, 2 workers in cluster mode, lib/puma/cluster.rb:337.
Describe the bug
I got a dependabot PR to update my app to the latest puma. When I try to boot the app, I'm getting a segfault. Here's the backtrace:
Backtrace
Puma config:
Here's my
config/puma.rb
:puma.rb
To Reproduce
I'll keep working on reproduction steps and digging into it, but I figured I'd get the bug in first in case it was an obvious/easy fix.
Desktop (please complete the following information):
Darwin 19.6.0; root:xnu-6153.141.2~1/RELEASE_X86_64 x86_64
The text was updated successfully, but these errors were encountered: