Ruby’s debugging story has improved dramatically in 3.x (and Rails).

I figured the best way to understand what’s happening in Campfire would be to attach the debugger and step through some of the more interesting parts.

Unfortunately, I was greeted with a recurring error that often looked something like this:

1
2
3
4
5
6
7
<Thread:0x00000001276a7750@DEBUGGER__::Server::reader /Users/scott/.asdf/installs/ruby/3.3.0/lib/ruby/gems/3.3.0/gems/debug-1.9.1/lib/debug/server.rb:44 aborting> terminated with exception (report_on_exception is true):
/Users/scott/.asdf/installs/ruby/3.3.0/lib/ruby/3.3.0/socket.rb:1128:in `unlink': No such file or directory @ apply2files - /var/folders/6q/xz6r4tqd4sl9qpbqkjlqj3dr0000gn/T/rdbg-501/rdbg-29191 (Errno::ENOENT)
	from /Users/scott/.asdf/installs/ruby/3.3.0/lib/ruby/3.3.0/socket.rb:1128:in `ensure in unix_server_socket'
/Users/scott/.asdf/installs/ruby/3.3.0/lib/ruby/3.3.0/socket.rb:1128:in `unlink'	from /Users/scott/.asdf/installs/ruby/3.3.0/lib/ruby/3.3.0/socket.rb:1128:in `unix_server_socket'
	from /Users/scott/.asdf/installs/ruby/3.3.0/lib/ruby/3.3.0/socket.rb:1169:in `unix_server_loop'
	from /Users/scott/.asdf/installs/ruby/3.3.0/lib/ruby/gems/3.3.0/gems/debug-1.9.1/lib/debug/server.rb:502:in `accept'
	from /Users/scott/.asdf/installs/ruby/3.3.0/lib/ruby/gems/3.3.0/gems/debug-1.9.1/lib/debug/server.rb:49:in `block in activate'

At first, I was convinced that debugging was busted on my computer. But I spun up a new project, and everything worked as expected.

Then, I thought about the error above showing up multiple times and the problems with threads I had previously mentioned.

I restarted the process without cluster mode enabled for Puma (WEB_CONCURRENCY=0) and could connect the debugger as expected.

From here, I decided to compare the puma.rb file in Campfire to the one in the empty Rails 7.1 project I just spun up, and I found the problem.

In the Puma configuration file, cluster mode is enabled if workers is greater than 0.

In a fresh Rails 7.1 puma.rb file, the worker configuration looks like this:

1
2
3
4
5
if ENV["RAILS_ENV"] == "production"
  require "concurrent-ruby"
  worker_count = Integer(ENV.fetch("WEB_CONCURRENCY") { Concurrent.physical_processor_count })
  workers worker_count if worker_count > 1
end

However, in Campfire, the RAILS_ENV check is removed

1
2
worker_count = (Concurrent.processor_count * 0.666).ceil
workers ENV.fetch("WEB_CONCURRENCY") { worker_count }

My guess is that with Campfire being a chat app with lots of connectivity, they opted for Puma’s cluster mode by default.

The good news is you can disable cluster mode in Campfire without changing any source. Just set the WEB_CONCURRENCY ENV to 0.

Something like this should do the trick:

WEB_CONCURRENCY=0 rdbg -n --open=vscode -c -- bin/rails server -p 3000