This is an automated email from the git hooks/post-receive script.
git pushed a commit to branch tymux
in repository terminology.
View the commit online.
commit f47b4074012b8b1c931cb0c9be622013395f8219
Author: [email protected] <[email protected]>
AuthorDate: Mon Mar 16 15:53:39 2026 -0600
fix: prevent SIGPIPE crash and use-after-free in tymux session teardown
When terminology closes a window connected to a tymux session, the process
crashed due to two issues:
1. SIGPIPE from closed socket: When the daemon exits, it closes its socket
end. On teardown, termsession_free() sends DETACH which raises SIGPIPE
with default fatal disposition. Added signal(SIGPIPE, SIG_IGN) to allow
the cleanup to complete.
2. Use-after-free from re-entrant callbacks: The fd handler could dispatch
callbacks on a partially-freed TermSession if _cb_session_data fired
during teardown. Fixed by nulling callbacks first (prevent re-entrant
firing), deleting the fd handler before DETACH (prevent use-after-free),
and making DETACH non-fatal (daemon may already be gone).
Fixes the session close crash reported in tymux integration testing.
Co-Authored-By: Claude Code <[email protected]>
---
src/bin/main.c | 9 +++++++++
src/bin/termsession.c | 20 ++++++++++++++++----
2 files changed, 25 insertions(+), 4 deletions(-)
diff --git a/src/bin/main.c b/src/bin/main.c
index ad679fb4..5d03db12 100644
--- a/src/bin/main.c
+++ b/src/bin/main.c
@@ -4,6 +4,7 @@
#include <locale.h>
#endif
+#include <signal.h>
#include <Ecore_Getopt.h>
#include <Elementary.h>
#include "main.h"
@@ -887,6 +888,14 @@ elm_main(int argc, char **argv)
terminology_starting_up = EINA_TRUE;
+#ifdef HAVE_TYMUX
+ /* Prevent SIGPIPE from killing terminology when writing to a socket
+ * whose remote end (tymuxd) has already exited. termsession_free()
+ * sends DETACH on teardown; if the daemon is gone the write raises
+ * SIGPIPE which — without this — terminates the process immediately. */
+ signal(SIGPIPE, SIG_IGN);
+#endif
+
#if defined(BINARY_TYFUZZ) || defined(BINARY_TYTEST)
eina_log_print_cb_set(_log_void, NULL);
#endif
diff --git a/src/bin/termsession.c b/src/bin/termsession.c
index 72d8fa05..cff9c6bf 100644
--- a/src/bin/termsession.c
+++ b/src/bin/termsession.c
@@ -489,17 +489,29 @@ termsession_free(TermSession *ts)
if (!ts)
return;
- /* Send clean disconnect */
- if (ts->sock_fd >= 0)
- termsrv_msg_send(ts->sock_fd, TSRV_MSG_DETACH, NULL, 0);
+ /* Null out all callbacks first so that no re-entrant call from any
+ * in-flight Ecore fd handler dispatch can fire cb_exit and attempt
+ * to delete an object that is already being torn down. */
+ ts->cb_change.func = NULL;
+ ts->cb_title.func = NULL;
+ ts->cb_bell.func = NULL;
+ ts->cb_exit.func = NULL;
- /* Remove fd handler before closing socket */
+ /* Remove the fd handler BEFORE sending DETACH. Sending DETACH to a
+ * socket whose remote end has already closed raises SIGPIPE (caught by
+ * the SIG_IGN set in elm_main) and returns an error; if we deleted the
+ * handler after the send, any pending data in the kernel buffer could
+ * still fire _cb_session_data on the next main-loop iteration. */
if (ts->handler)
{
ecore_main_fd_handler_del(ts->handler);
ts->handler = NULL;
}
+ /* Send clean disconnect — error is non-fatal, daemon may already be gone */
+ if (ts->sock_fd >= 0)
+ termsrv_msg_send(ts->sock_fd, TSRV_MSG_DETACH, NULL, 0);
+
if (ts->shm && ts->shm != MAP_FAILED)
{
munmap(ts->shm, ts->shm_size);
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.