fix(ui): iterate main context inside synchronous input loops
inp_get_line() / inp_get_password() loop `while (!x) { inp_readline();
ui_update(); }` with no g_main_context_iteration call. If such a prompt
is raised from a network handler during an editor session — realistic
triggers are TLS-cert verification on a reconnect (sv_ev_certfail ->
ui_get_line() in src/event/server_events.c) and PGP passphrase on an
incoming encrypted message (ui_ask_pgp_passphrase() in src/pgp/gpg.c) —
the main thread is parked in this loop. inp_readline returns NULL
(suspended), ui_update returns (ui_suspended), and the editor child
watch never dispatches because the main loop never reaches its own
g_main_context_iteration. is_suspended stays TRUE forever, the loop
never receives input, and the app deadlocks until killed externally.
Run the GLib iteration inside the loop body so the child watch can
dispatch, _editor_exit_cb fires, ui_resume clears suspension, and the
next inp_readline reads from the terminal — letting the user answer the
deferred prompt once the editor is closed.
This commit is contained in:
@@ -325,6 +325,10 @@ inp_get_line(void)
|
||||
while (!line) {
|
||||
line = inp_readline();
|
||||
ui_update();
|
||||
// Let GLib sources (notably the editor child watch) dispatch so
|
||||
// ui_resume can run if the prompt was raised mid-editor-session.
|
||||
while (g_main_context_iteration(NULL, FALSE))
|
||||
;
|
||||
}
|
||||
status_bar_clear_prompt();
|
||||
return line;
|
||||
@@ -356,6 +360,10 @@ inp_get_password(void)
|
||||
while (!password) {
|
||||
password = inp_readline();
|
||||
ui_update();
|
||||
// Let GLib sources (notably the editor child watch) dispatch so
|
||||
// ui_resume can run if the prompt was raised mid-editor-session.
|
||||
while (g_main_context_iteration(NULL, FALSE))
|
||||
;
|
||||
}
|
||||
get_password = FALSE;
|
||||
status_bar_clear_prompt();
|
||||
|
||||
Reference in New Issue
Block a user