Skip to content

Stop the publisher cluster as well as the subscriber (#470) - #471

Merged
ChronicallyJD merged 1 commit into
commandprompt:mainfrom
ChronicallyJD:fix/470-subscriber-cluster-leak
Aug 7, 2026
Merged

Stop the publisher cluster as well as the subscriber (#470)#471
ChronicallyJD merged 1 commit into
commandprompt:mainfrom
ChronicallyJD:fix/470-subscriber-cluster-leak

Conversation

@ChronicallyJD

Copy link
Copy Markdown
Collaborator

Closes #470.

The defect

pgc_setup installs trap pgc_teardown EXIT. test/logical_subscriber.sh then installed its own:

sub_cleanup() { pgc_pg "pg_ctl -D '$SUB_DIR' -m immediate stop" >/dev/null 2>&1 || true; }
trap sub_cleanup EXIT

A second trap ... EXIT replaces the first. So the subscriber cluster was stopped and the suite's own cluster never was. The suite passed, every run, and left a live postmaster behind.

Measured, not argued

PG17, from a box reaped to zero orphaned postmasters:

before fix:  logical_subscriber  rc=0  before=0 after=1 delta=1  PASSED
after fix:   logical_subscriber  rc=0  before=0 after=0 delta=0  PASSED

Gated on PG18 and PG19, with replication.sh alongside because it is the suite that already chained correctly and must keep doing so:

PG18  logical_subscriber  rc=0  checks run: 20  PASSED
PG18  replication         rc=0  checks run: 41  PASSED
PG19  logical_subscriber  rc=0  checks run: 20  PASSED
PG19  replication         rc=0  checks run: 41  PASSED

Why it is not cosmetic

The port band is finite. A suite that cannot get a port fails after 8 start attempts with could not create any TCP/IP sockets, which is indistinguishable from a real red and is attributed to whichever suite drew the exhausted port, not to the one that leaked. 37 orphans had accumulated on the dev container and turned two majors of a gate red for reasons unrelated to the code under test.

The audit behind it

objstore_module had the identical defect and was fixed in #446. This is the other one.

The audit had to be measured rather than read, and that mattered: harness_selftest installs its own EXIT trap at line 73, before pgc_setup at line 90, so by inspection pgc_setup should clobber it and the squatter cluster should leak. Measured, it does not.

suite delta verdict
harness_selftest 0 no leak, despite the ordering
logical_subscriber 1 -> 0 this PR
replication 0 already correct, chains pgc_teardown
objstore_module 1 -> 0 fixed in #446

Left open deliberately

Nothing in the harness detects this class. A suite can leak a cluster and still report PASSED, which is how both instances survived unnoticed. #470 records that a before/after postmaster count around each suite would catch the whole category rather than these two instances; that is a harness change and not this PR.

…ommandprompt#470)

pgc_setup installs `trap pgc_teardown EXIT`. This suite then ran

    trap sub_cleanup EXIT

which REPLACES it rather than adding to it, so sub_cleanup stopped the subscriber
and the suite's own cluster was never stopped. The suite passed and left a live
postmaster behind it every run.

Measured on PG17, from a box reaped to zero orphans: delta 1 before, delta 0
after, PASSED both times. Gated on PG18 and PG19, with replication.sh alongside
because it is the suite that already had this right and must stay right: 20 and 41
checks, all green.

Why this is not cosmetic: the port band is finite, and a suite that cannot get a
port fails after 8 start attempts with "could not create any TCP/IP sockets". That
is indistinguishable from a real failure, and it lands on whichever suite happened
to draw the exhausted port rather than on the one that leaked. 37 orphans had
accumulated on the dev box and turned two majors of a gate red for reasons that
had nothing to do with the code under test.

objstore_module had the identical defect and was fixed in commandprompt#446. This is the last
of the two the audit found. Worth noting that the audit had to be MEASURED rather
than read: harness_selftest installs its own EXIT trap BEFORE pgc_setup, so by
inspection pgc_setup should clobber it and leak the squatter, and it does not.

Nothing detects this class of bug. A suite can leak a cluster and still report
PASSED, which is why both instances survived until the band ran out. commandprompt#470 records
that a harness-level before/after postmaster count would catch the category.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01L2DvnWDM7g27ubDCQdXhky
@ChronicallyJD
ChronicallyJD merged commit 065c208 into commandprompt:main Aug 7, 2026
11 checks passed
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.

logical_subscriber leaks its cluster: a suite's own EXIT trap replaces pgc_teardown

2 participants