Repository navigation
Conversation
catch_terminate() only sets GotTerminate, and CHANreadloop() checked it after the select() result: a signal that arrives while innd waits in select() makes it return -1 with EINTR, and the loop went straight back into select(). The signal was only acted on at the next connection or when select() timed out (the remaining part of the timer, up to several minutes), so kill or docker stop usually ended in a SIGKILL without the active file and history being flushed. Check GotTerminate right after select() returns, whatever its result. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The bug is not limited to innd having no connection: it happens whenever innd waits in select(), with idle connections open too, and also for SIGINT with -d. It was introduced by 9b1b651 (5fa1209 in 2.5.4), which moved the GotTerminate check below the EINTR "continue" so that STATUSmainloophook() could no longer overwrite errno before the EINTR test. The previous commit restores the check before "count < 0" and keeps that errno fix: nothing touches errno unless innd exits. Stopping innd with a signal is what kill does, and what docker and systemd do (followed by SIGKILL after their stop timeout); stopping it with ctlinnd shutdown, as rc.news stop does, was never affected. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A termination signal that arrives while innd is not in select() is blocked by the signal mask. xsignal_unmask() right before select() then runs the handler, so select() is not interrupted and innd waits for the whole timeout (or the next activity) before it checks GotTerminate. Before signal masking, the handler ran at once but select() waited the same way, so this is older than the idle case. When GotTerminate is set after the unmask, use a zero timeout so that select() returns at once and the check right after it is reached. A window of a few instructions between that test and select() remains; closing it would need pselect() or a self-pipe. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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.
This is the follow-up announced in #376 and builds on it.
The first two commits are those of #376; the new change is the last commit, bc3424b.
Problem
A SIGTERM or SIGHUP that arrives while innd is busy (not waiting in
select()), for instance while a Perlfilter_artruns, is blocked by the signal mask.xsignal_unmask()right beforeselect()then runs the handler, which setsGotTerminate, butselect()is not interrupted by it.innd waits for the whole timeout or the next activity before it reaches the
GotTerminatecheck.Before signal masking, the handler ran at once but
select()waited the same way, so this part is older than the idle case of #376.Fix
When
GotTerminateis set after the unmask, use a zero timeout, so thatselect()returns at once and the check right after it (moved there by #376) is reached:A window of a few instructions between that test and
select()remains.Closing it completely would need
pselect()or a self-pipe, which seemed too much here.The
news.podentry of #376 gets one sentence for this case.Testing
A Perl
filter_innd.plwhosefilter_artsleeps, an article fed with IHAVE, SIGTERM during the sleep:sleepinJustCleanup())make testpasses.TestSIGTERMWhileBusyin tests/e2e/signal_test.go. It fails with innd: exit on SIGTERM and SIGHUP while waiting for activity #376 alone (Fedora 45) and passes with this fix (Fedora 45 and GitHub Actions).