Skip to content

Database Rake tasks can leak or unbalance writer stack frames #315

Description

@OskarEichler

Describe the bug
Database tasks are enhanced with a push prerequisite and an appended pop action. If the original action raises, Rake skips the appended cleanup and leaves the writing-role frame on ActiveRecord::Base.connected_to_stack. Nested database tasks also reuse the already-invoked push task, allowing the inner cleanup to pop the outer task frame.

Steps to reproduce

require 'bundler/inline'

gemfile do
  source 'https://rubygems.org'

  gem 'activerecord', '8.1.3.1'
  gem 'active_record_proxy_adapters', '0.11.1'
  gem 'rake'
end

require 'active_record'
require 'active_record_proxy_adapters/rake'

Rake.application = Rake::Application.new
ActiveRecordProxyAdapters::Rake.load_tasks
Rake::Task.define_task('db:raises') { raise 'boom' }
ActiveRecordProxyAdapters::Rake.enhance_db_tasks

before = ActiveRecord::Base.connected_to_stack.length
begin
  Rake::Task['db:raises'].invoke
rescue RuntimeError
end
after = ActiveRecord::Base.connected_to_stack.length

p [before, after]

A nested reproduction similarly observes stack depths [1, 1, 0] across the outer action, inner action, and resumed outer action instead of [1, 2, 1].

Expected behavior

Every database task owns one writing-role frame and removes it in exception-safe cleanup. The example prints [0, 0], and nested tasks retain the outer frame until the outer task completes.

Actual behavior

The example prints [0, 1]. A raised task leaks its frame, and a nested task can pop the frame still needed by its caller.

System configuration

Active Record version: 8.1.3.1
Active Record proxy adapters version: 0.11.1
Ruby version: 4.0.6

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions