Skip to content

Fix lifecycle cleanup for transient request callbacks - #1877

Open
fglock wants to merge 12 commits into
masterfrom
feature/issue-1646-lifecycle
Open

fglock wants to merge 12 commits into
masterfrom
feature/issue-1646-lifecycle

Conversation

@fglock

@fglock fglock commented Oct 24, 2026 •

Copy link
Copy Markdown
Owner

Summary

  • Recheck conservatively preserved weak referents at statement boundaries after transient owners unwind, even while unrelated temporary roots remain.
  • Keep aggregate array slots from being treated as named lexical bindings.
  • Align B::REFCNT with native B when inspecting a reference stored in a hash field during DESTROY.
  • Re-fire DESTROY when a resurrected object's final captured owner is released, even if a conservative root snapshot still contains the earlier caller frame.
  • Sweep nested weak references after blessed container cleanup returns, clearing the DBIx::Class Storage callback when its Schema is gone.
  • Add focused regressions for weak-reference lifecycle, B::REFCNT, captured caller arguments, and nested weak-reference cleanup.

Fixes #1794
Refs #1646

Validation

  • nice -n 19 make — passed on the PR candidate.
  • make check-links — passed.
  • Existing system Perl oracles for the focused lifecycle regressions — passed.
  • DestroyDispatchNestedWeakSweepTest fails on the PR parent 05f9121f1 and passes on the candidate on both JVM and interpreter backends.
  • DBIx::Class t/storage/txn_scope_guard.t — 18/18 assertions pass after the re-fire fix.
  • DBIx::Class t/storage/error.t — 49/49 assertions pass on JPerl and system Perl; this includes the previously failing callback-after-Schema-destruction assertion.

The full CPAN release acceptance run remains outstanding. The prior run had one Mojolicious t/mojo/asset.t failure because that test requires unsupported fork; the separate promise timeout passed on retry. DBIx::Class exceeded its 5,400-second target limit. Rerun the full acceptance matrix after lifecycle follow-ups #1794 and #1795 settle; this PR does not claim that the #1646 matrix is complete.

@fglock
fglock force-pushed the feature/issue-1646-lifecycle branch from 62cbfef to 7bb2a07 Compare October 24, 2026 02:00
fglock and others added 11 commits October 25, 2026 19:48
Recheck conservatively retained weak referents once their transient owners
unwind, without letting unrelated temporary roots postpone cleanup. Keep
aggregate array slots from being mistaken for named lexical bindings and add
lifecycle regressions for callback and Mojolicious request ownership.

Refs #1646

Generated with [Codex](https://openai.com/codex)

Co-Authored-By: Codex <158243242+codex[bot]@users.noreply.github.com>
Recheck targeted weak-sweep candidates against current temporary, package,
and lexical roots at the statement boundary. Keep candidates that acquired a
live owner after the sweep was queued, while still releasing targets retained
only by unrelated temporary roots.

Add regression coverage for a candidate that gains a live lexical owner before
an unrelated temporary root is drained.

Generated with [Codex](https://openai.com/codex)

Co-Authored-By: Codex <158243242+codex[bot]@users.noreply.github.com>
Remove targeted sweep candidates once a persistent Perl root proves they
remain live. Their lexical or package owner will request a fresh sweep on
release, while temporary-root candidates stay queued for a later boundary.
Check live lexical roots before constructing the larger package snapshot.

The full unit gate passes. The CPAN acceptance run upgrades Catalyst from
FAIL to PASS; DBIx::Class and Mojolicious remain qualification gaps.

Generated with [Codex](https://openai.com/codex/)

Co-Authored-By: Codex <codex@openai.com>
Remove the special increment that made B::REFCNT report a sole hash-field
owner as multiple owners during DESTROY. Add a regression test for the native
Perl count and expose direct hash-slot owners in internal refstate diagnostics.

The complete `make` gate and the new system Perl/JVM/interpreter regression
checks pass. DBIx::Class release qualification still has separate failures.

Refs #1646

Generated with [Codex](https://openai.com/codex)

Co-Authored-By: Codex <158243242+codex[bot]@users.noreply.github.com>
When a resurrected object's final counted owner is released, invoke DESTROY
again before conservative weak-root recovery can restore it from a stale caller
snapshot. This restores DBIx::Class::Storage::TxnScopeGuard's duplicate
DESTROY warning after captured caller arguments are cleared.

Add focused coverage for a weakly registered transaction guard captured from a
DESTROY warning. The full make gate, system Perl oracle, and both JPerl
backends pass; DBIx::Class storage/error qualification still has one failure.

Refs #1646

Generated with [Codex](https://openai.com/codex)

Co-Authored-By: Codex <158243242+codex[bot]@users.noreply.github.com>
Capture the expected DESTROY warning with a local __WARN__ handler so the
regression test runs in the minimal GitHub Actions environment.

Generated with OpenAI Codex (https://openai.com/codex/)

Co-Authored-By: OpenAI Codex <chatgpt@users.noreply.github.com>
Record direct hash-slot ownership weakly so stale owners can be excluded
from B::REFCNT results during destruction. Keep slot records accurate as
scalar ownership changes and add a regression for a hash owner leaving scope.

Generated with Codex (https://openai.com/codex)

Co-Authored-By: Codex <codex@openai.com>
Record the system Perl and clean-master comparison for DBIx::Class assertion 49,
and keep the case open pending lifecycle work and full acceptance.

Generated with Codex (https://openai.com/codex)

Co-Authored-By: Codex <codex@openai.com>
Record system Perl, clean-master, and lifecycle-candidate outcomes for the
DBIx leak and transaction guard tests without claiming acceptance.

Generated with Codex (https://openai.com/codex)

Co-Authored-By: Codex <codex@openai.com>
Record that the reduced DBIx scope-guard capture case passes on both backends,
while the full upstream test still fails in its broader suite context.

Generated with Codex (https://openai.com/codex)

Co-Authored-By: Codex <codex@openai.com>
Record the clean-candidate results for the three DBIx lifecycle files and
keep storage/error.t assertion 49 open pending #1642 reconciliation.

Generated with [Codex](https://openai.com/codex)

Co-Authored-By: Codex <codex@openai.com>
@fglock
fglock force-pushed the feature/issue-1646-lifecycle branch from 40280fd to 05f9121 Compare October 25, 2026 23:23
Request a weak-reference sweep after blessed container cleanup completes so
DBIx::Class callbacks no longer retain a dead Storage object through an
inflated selective reference count. Cover the callback lifecycle on both
execution backends and record the fix in the changelog.

Generated with OpenAI Codex (https://openai.com/codex/)

Co-Authored-By: OpenAI Codex <codex@openai.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Mojolicious controller and WebSocket lifetimes regress with #1642 integration

1 participant