Skip to content

Exit without stopping when there is nothing to stop - #23

Merged
cressie176 merged 1 commit into
mainfrom
exit-nothing-to-stop
Sep 28, 2026
Merged

cressie176 merged 1 commit into
mainfrom
exit-nothing-to-stop

Conversation

@cressie176

Copy link
Copy Markdown
Member

Closes #22.

system.exit(code) called from the rejection of a failed start() announced a second, empty stop pair. The stop which follows a failed start had already reset the system, so the stop() inside exit ran a fresh stop which skipped every component and announced itself regardless.

Behaviour

  • exit() on a system with nothing to stop exits at once and announces no stop. Nothing to stop means no start in flight, no stop in flight or left failed, and no component started: a system which never started, has already stopped, or whose start failed and the stop which followed has finished.
  • A stop which failed leaves components started, so an exit after it still retries the stop and the code still reflects the outcome. A new scenario guards this so the check cannot skip too much.
  • A bare stop() after a failed start is unchanged and still announces the empty pair, by the existing rule in system-events.md that an operation with nothing to do is announced like any other. The alternative, making stop() silent on a stopped system, would have overruled that rule and the two-pair assertion in "Stopping a system which has already stopped".

Found empirically

  • The existing "announced X before exiting" step used includes, so it could not see a duplicate. The exiting library gains a step which compares the whole event trace the child program printed as a table.
  • The child program's exit wrapper returned nothing, which only surfaced once a behaviour replaced start() and the program tried to chain on it.
  • Dropping the start-in-flight term of the check fails "An exit while the system is starting", so each term of the guard is load-bearing except the stop-in-flight one, which only matters in a window no child-process scenario can reach without contortion; see the issue comment.

Tests

Four new child-process scenarios in test/features/exiting.md: three red before the fix with the duplicate pair visible in the diff, green after, and red again with the guard broken. 1357 steps pass, lint and typecheck clean.

🤖 Generated with Claude Code

Calling exit() from the rejection of a failed start announced a second
stop pair, so an application logging system_stop_succeeded reported one
shutdown twice. The stop which follows a failed start had already reset
the system, and exit() then ran a fresh stop which skipped every
component and announced itself regardless.

Both stops were doing what they were told, so one of them had to stay
quiet. Making stop() silent on a stopped system would overrule the rule
that an operation with nothing to do is announced like any other, which
the system events feature asserts and which lets a listener on
system_stop_succeeded see every stop however it was triggered. So exit()
now checks whether there is anything to stop: no start in flight, no
stop in flight or left failed, and no component started. When there is
not, the process exits at once and no stop is announced. A stop which
failed leaves components started, so an exit after it still retries the
stop and reports its outcome in the code.

The exiting scenarios gain a step which compares the whole event trace
the program printed, since the existing step only checked that an event
appeared and could not see a duplicate.

Closes #22

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@codecov-commenter

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 100.00%. Comparing base (69ebff3) to head (6a24a70).

Additional details and impacted files
@@            Coverage Diff            @@
##              main       #23   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files           12        12           
  Lines          801       810    +9     
=========================================
+ Hits           801       810    +9     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@cressie176
cressie176 merged commit 900f3bb into main Sep 28, 2026
6 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.

exit() after a failed start announces a second, empty stop

2 participants