Stop quit[] from ending the host process - #181
Open
HugoFara wants to merge 1 commit into
Open
Conversation
quit is in the script command table, so it is reachable from the Python binding and from the HTTP server, and it called exit(0). A host got no exception and no traceback, its finally blocks and atexit handlers never ran, buffered output was lost, and the status was 0 — so a batch job recorded success having stopped early. quit now releases the session and records the request; quitRequested() exposes it and clearQuitRequest() forgets it. The shell in app/forefire is what leaves: both the interactive loop and the HTTP listen loop check it, so a served quit[] still stops the server. executeLoop stops reading a script after one, rather than the process disappearing mid-file. currentSession.params is no longer deleted. It is the SimulationParameters singleton, owned by GetInstance() and shared with every other holder, so deleting it left GetInstance() handing out a dangling pointer. That went unnoticed only because exit() followed on the next line; without the exit it would be a use-after-free on the next parameter read. The safe topology error path called quit() too, so an internal failure terminated the host on its own, with status 0. It reports and returns error instead. The message moves to stderr and is no longer gated on commandOutputs: a returned error nobody is obliged to check should not also be silent. tests/unit/test_quit_command.cpp covers it, and the CTest entries now require doctest's closing 'Status: SUCCESS!' line. Without that a suite whose process exits mid-run reports as a pass, because ctest sees 0 and does not look for the summary that never printed — the first version of this test passed happily with exit(0) still in place. Verified with the reproduction from #160: before quit[] / AFTER quit[] / FINALLY ran / ATEXIT ran, exit 0 against the previous output, which was 'before quit[]' and a dead interpreter. Unit suite 5/5; runff KML and NetCDF match. Closes #160
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #160.
quitis in the script command table, so it is reachable from the Python binding and from the HTTP server, and it calledexit(0). The reproduction from the issue, before and after:That one line gave no exception to catch, skipped
finallyandatexit, lost buffered output, and returned status 0 — so a batch job records success having stopped early.What changed
quitnow releases the session and records the request;Command::quitRequested()exposes it andclearQuitRequest()forgets it. The shell inapp/forefireis what leaves. Both the interactive loop and the HTTP listen loop check, so aquit[]served over HTTP still stops the server. An embedder is free to ignore the request.quitwas also deletingcurrentSession.params, which is theSimulationParameterssingleton, shared with every other holder. Only theexit()on the next line hid it; removing the exit alone would have turned this into a use-after-free on the next parameter read. It is no longer deleted.@filippi — the safe topology path is your call
Command.cpp:1125calledquit()from acatch (...)in the atmospheric step loop, under// TODO supersafe mode ?, so an internal failure ended the host process with status 0. It now reports and returnserror. This changes behaviour in coupled runs: a safe-topology failure no longer terminates, and the caller continues. If a hard stop needs to stay reachable there, say so and I will make it a distinct command the binding does not expose, as #160 suggests.Verification
Reproduction from #160 passes, output above. Unit suite 5/5 with three new cases. All five CTest entries now require doctest's closing
Status: SUCCESS!line, so an earlyexit(0)fails the suite instead of passing it — without that, my first test passed with the bug still in place.runffKML and NetCDF both match within tolerance.This pull request, including its code changes and this description, was generated by Claude Opus 5, and reviewed manually before submitting.
EDIT: rewrote for human readability.