refactor(exit): pass error message to preserve_exit() (#22097)

Problem:
1. Some calls to preserve_exit() don't put a message in IObuff, so the
   IObuff printed by preserve_exit() contains unrelated information.
2. If a TUI client runs out of memory or receives a deadly signal, the
   error message is shown on alternate screen and cannot be easily seen
   because the TUI exits alternate screen soon afterwards.

Solution:
Pass error message to preserve_exit() and exit alternate screen before
printing it.

Note that this doesn't fix the problem that server error messages cannot
be easily seen on exit. This is tracked in #21608 and #21843.
This commit is contained in:
zeertzjq 2023-02-04 20:14:31 +08:00 committed by GitHub
parent 90333b24c3
commit 69bb145cea
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 21 additions and 30 deletions

View File

@ -155,7 +155,7 @@ static void fread_idle_cb(uv_idle_t *handle)
uintmax_t fpos_intmax = stream->fpos;
if (fpos_intmax > INT64_MAX) {
ELOG("stream offset overflow");
preserve_exit();
preserve_exit("stream offset overflow");
}
// Synchronous read

View File

@ -211,9 +211,7 @@ static int nlua_luv_cfpcall(lua_State *lstate, int nargs, int nresult, int flags
if (status) {
if (status == LUA_ERRMEM && !(flags & LUVF_CALLBACK_NOEXIT)) {
// consider out of memory errors unrecoverable, just like xmalloc()
os_errmsg(e_outofmem);
os_errmsg("\n");
preserve_exit();
preserve_exit(e_outofmem);
}
const char *error = lua_tostring(lstate, -1);

View File

@ -790,10 +790,10 @@ void getout(int exitval)
os_exit(exitval);
}
/// Preserve files, print contents of `IObuff`, and exit 1.
/// Preserve files, print contents of `errmsg`, and exit 1.
///
/// May be called from deadly_signal().
void preserve_exit(void)
void preserve_exit(const char *errmsg)
FUNC_ATTR_NORETURN
{
// 'true' when we are sure to exit, e.g., after a deadly signal
@ -812,12 +812,15 @@ void preserve_exit(void)
// Ignore SIGHUP while we are already exiting. #9274
signal_reject_deadly();
if (ui_client_channel_id) {
// For TUI: exit alternate screen so that the error messages can be seen.
ui_client_stop();
}
os_errmsg(errmsg);
os_errmsg("\n");
if (ui_client_channel_id) {
os_exit(1);
}
os_errmsg(IObuff);
os_errmsg("\n");
ui_flush();
ml_close_notmod(); // close all not-modified buffers

View File

@ -121,9 +121,7 @@ void *xmalloc(size_t size)
{
void *ret = try_malloc(size);
if (!ret) {
os_errmsg(e_outofmem);
os_errmsg("\n");
preserve_exit();
preserve_exit(e_outofmem);
}
return ret;
}
@ -152,9 +150,7 @@ void *xcalloc(size_t count, size_t size)
try_to_free_memory();
ret = calloc(allocated_count, allocated_size);
if (!ret) {
os_errmsg(e_outofmem);
os_errmsg("\n");
preserve_exit();
preserve_exit(e_outofmem);
}
}
return ret;
@ -174,9 +170,7 @@ void *xrealloc(void *ptr, size_t size)
try_to_free_memory();
ret = realloc(ptr, allocated_size);
if (!ret) {
os_errmsg(e_outofmem);
os_errmsg("\n");
preserve_exit();
preserve_exit(e_outofmem);
}
}
return ret;
@ -194,8 +188,7 @@ void *xmallocz(size_t size)
{
size_t total_size = size + 1;
if (total_size < size) {
os_errmsg(_("Vim: Data too large to fit into virtual memory space\n"));
preserve_exit();
preserve_exit(_("Vim: Data too large to fit into virtual memory space\n"));
}
void *ret = xmalloc(total_size);

View File

@ -550,8 +550,7 @@ static void read_error_exit(void)
if (silent_mode) { // Normal way to exit for "nvim -es".
getout(0);
}
STRCPY(IObuff, _("Vim: Error reading input, exiting...\n"));
preserve_exit();
preserve_exit(_("Vim: Error reading input, exiting...\n"));
}
static bool pending_events(MultiQueue *events)

View File

@ -172,11 +172,10 @@ static void deadly_signal(int signum)
ILOG("got signal %d (%s)", signum, signal_name(signum));
snprintf(IObuff, sizeof(IObuff), "Vim: Caught deadly signal '%s'\r\n",
signal_name(signum));
snprintf(IObuff, IOSIZE, "Vim: Caught deadly signal '%s'\r\n", signal_name(signum));
// Preserve files and exit.
preserve_exit();
preserve_exit(IObuff);
}
static void on_signal(SignalWatcher *handle, int signum, void *data)

View File

@ -458,9 +458,6 @@ static void tui_terminal_stop(TUIData *tui)
void tui_stop(TUIData *tui)
{
if (tui->stopped) {
return;
}
tui_terminal_stop(tui);
stream_set_blocking(tui->input.in_fd, true); // normalize stream (#2598)
tinput_destroy(&tui->input);
@ -470,7 +467,7 @@ void tui_stop(TUIData *tui)
}
/// Returns true if UI `ui` is stopped.
static bool tui_is_stopped(TUIData *tui)
bool tui_is_stopped(TUIData *tui)
{
return tui->stopped;
}

View File

@ -122,7 +122,9 @@ void ui_client_run(bool remote_ui)
void ui_client_stop(void)
{
tui_stop(tui);
if (!tui_is_stopped(tui)) {
tui_stop(tui);
}
}
void ui_client_set_size(int width, int height)