Skip to content

fix(cli, rfd): Escalate Ctrl-C only on unanswered presses - #988

Open
JeanMertz wants to merge 2 commits into
mainfrom
interrupt-fix
Open

fix(cli, rfd): Escalate Ctrl-C only on unanswered presses#988
JeanMertz wants to merge 2 commits into
mainfrom
interrupt-fix

Conversation

@JeanMertz

Copy link
Copy Markdown
Collaborator

EscalationState reset the Ctrl-C press count on elapsed time alone, so a press an interrupt menu had already answered stayed on the escalation ladder. Answering the streaming menu and interrupting again inside the two-second cooldown counted as a second press, which bypasses the handler stack and requests a graceful shutdown, so the run ended with no menu and no message. Answering the menu quickly made the next Ctrl-C fatal; taking longer than the cooldown left it working.

A delivered press is now an InterruptNotice that the notified event loop resolves. handled() clears the count, decline() hands the press to the next handler down with the count intact, and dropping it leaves the press on the ladder, which is the safe default for a handler that was notified but produced nothing visible. Only presses that produced nothing escalate.

Carrying the reset on the delivered value rather than on the router means an event loop cannot decide what a press did without holding the value that records the decision, so the ladder behaves the same at every handler site. lock.rs and plugin/dispatch.rs had the same defect and now resolve their presses too.

inline_select returning Err mapped every error to an escalation, conflating the user cancelling the menu with the menu being unable to run at all. The latter now yields PromptFailed, which leaves the turn untouched and the press on the ladder, so a second Ctrl-C gets the user out through the router instead of through a prompt that is not working.

The interrupt path also logs the resolved action, the decision the handler reached, and the InquireError behind a prompt that returned without a selection. That error was discarded as Err(_), and its absence is why diagnosing this took several rounds of guessing.

RFD 045 is updated to match: the ladder counts unanswered presses, and SignalRouter::decline is replaced by resolving the notice. T0014 stays open, since the traces that opened it showed a different signature and are no longer available.

`EscalationState` reset the Ctrl-C press count on elapsed time alone,
so a press an interrupt menu had already answered stayed on the
escalation ladder. Answering the streaming menu and interrupting
again inside the two-second cooldown counted as a second press, which
bypasses the handler stack and requests a graceful shutdown, so the
run ended with no menu and no message. Answering the menu quickly
made the next Ctrl-C fatal; taking longer than the cooldown left it
working.

A delivered press is now an `InterruptNotice` that the notified event
loop resolves. `handled()` clears the count, `decline()` hands the
press to the next handler down with the count intact, and dropping it
leaves the press on the ladder, which is the safe default for a
handler that was notified but produced nothing visible. Only presses
that produced nothing escalate.

Carrying the reset on the delivered value rather than on the router
means an event loop cannot decide what a press did without holding
the value that records the decision, so the ladder behaves the same
at every handler site. `lock.rs` and `plugin/dispatch.rs` had the
same defect and now resolve their presses too.

`inline_select` returning `Err` mapped every error to an escalation,
conflating the user cancelling the menu with the menu being unable to
run at all. The latter now yields `PromptFailed`, which leaves the
turn untouched and the press on the ladder, so a second Ctrl-C gets
the user out through the router instead of through a prompt that is
not working.

The interrupt path also logs the resolved action, the decision the
handler reached, and the `InquireError` behind a prompt that returned
without a selection. That error was discarded as `Err(_)`, and its
absence is why diagnosing this took several rounds of guessing.

RFD 045 is updated to match: the ladder counts unanswered presses,
and `SignalRouter::decline` is replaced by resolving the notice.
T0014 stays open, since the traces that opened it showed a different
signature and are no longer available.

Signed-off-by: Jean Mertz <git@jeanmertz.com>
Signed-off-by: Jean Mertz <git@jeanmertz.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.

1 participant