Open
Description
Describe the bug
Bugsnag's delivery thread can checkout an ActiveRecord database connection that is never returned to the pool. This causes subsequent connections to time out waiting for a connection from the pool.
Steps to reproduce
- An ActiveJob job receives an ActiveRecord instance as a job argument
- The job raises an exception
- Bugsnag creates a report that contains the serialized job arguments
- The ActiveRecord class overrides
to_s
which is called when it gets serialized by bugsnag. Theto_s
method contains code that queries the database. - Bugsnag's delivery thread checks out a database connection from the connection pool when the
to_s
method is invoked byBugsnag::Cleaner#traverse_object
- The connection pool has now permanently lost a connection to the bugsnag delivery thread
Environment
- Bugsnag version: 6.26.0
- Ruby version: 3.0.5
- Bundle version: 2.3.26
- Integration framework version:
- Que:
- Rack 2.2.8
- Rails: 6.1.6
- Rake:
- Sidekiq: 7.1.2
- Other:
Example code snippet
# Run a single instance of sidekiq worker with concurrency 2
class Foo < ApplicationRecord
def to_s
Bar.first # Database query triggered during bugsnag report delivery
"foo"
end
end
class Bar < ApplicationRecord
end
class MyJob < ApplicationJob
def perform(foo)
Bar.first # Query will time out waiting for connection
sleep 10
raise "Fail"
end
end
Foo.create
Bar.create
10.times { MyJob.perform_later(Foo.first) }
Error messages: