Compare commits

..

1 Commits

Author SHA1 Message Date
c4e2e46636 feat(editor): add asynchronous external editor support
Some checks failed
CI / Check spelling (pull_request) Successful in 17s
CI / Check coding style (pull_request) Successful in 30s
CI / Linux (fedora) (pull_request) Failing after 1m24s
CI / Linux (arch) (pull_request) Failing after 3m33s
CI / Linux (debian) (pull_request) Successful in 11m10s
CI / Linux (ubuntu) (pull_request) Successful in 11m38s
The synchronous `get_message_from_editor` blocked the main loop (`prof_run`) while launching an external editor like `vim`, halting network I/O in `session_process_events` and preventing incoming message reception.

Introduced `get_message_from_editor_async` for `cmd_editor` to run the editor asynchronously. It forks and execs the editor in a thread (`editor_thread`), suspending NCurses to free the terminal. The main loop skips `inp_readline` and `ui_update` via a new `background_mode` flag while the editor runs, allowing `session_process_events` to keep the connection alive.

On editor completion, `editor_process` (called per loop iteration) resumes NCurses with `ui_resize`, inserts the result into the readline buffer and clears `background_mode`.

Retained synchronous `get_message_from_editor` for ~20 existing code paths (e.g., `vcard_nickname`) to avoid breaking them.

Tested with `vim` and `nano`: confirms no rendering conflicts, messages received during editing, and seamless resume. Edge cases like editor crashes handled via error logging and seamless resume.
2025-08-07 02:40:51 +02:00

View File

@@ -71,7 +71,11 @@ editor_thread(void* arg)
if (pid > 0) {
task->pid = pid;
int status;
// Unlock mutex to avoid deadlock on the main loop
pthread_mutex_unlock(&task->mutex);
waitpid(pid, &status, 0);
pthread_mutex_lock(&task->mutex);
gsize length;
if (!g_file_get_contents(task->filename, &task->result, &length, &task->error)) {
log_error("[Editor] could not read from %s: %s", task->filename,
@@ -165,6 +169,7 @@ get_message_from_editor_async(gchar* message)
// Set background mode
background_mode = TRUE;
log_debug("[Editor] Entering background mode");
// Start editor thread
if (pthread_create(&editor_task.thread, NULL, editor_thread, &editor_task) != 0) {
@@ -178,6 +183,7 @@ get_message_from_editor_async(gchar* message)
editor_task.editor_cmd = NULL;
pthread_mutex_unlock(&editor_task.mutex);
background_mode = FALSE;
log_debug("[Editor] Exiting background mode");
reset_prog_mode();
doupdate();
log_error("[Editor] Failed to create editor thread");
@@ -220,6 +226,7 @@ editor_process(ProfWin* window)
}
pthread_mutex_unlock(&editor_task.mutex);
background_mode = FALSE;
log_debug("[Editor] Exiting background mode");
}
// Deprecated synchronous editor call. Returns a message as returned_message.