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.

Reply via email to