From cfe6a7812236662c943791b8b252cbde9db0ed3a Mon Sep 17 00:00:00 2001 From: hecko Date: Mon, 13 Jul 2026 03:32:56 +0000 Subject: [PATCH] tcp_trsp: don't drop sock_mut mid-send in send()/check_connection send() and check_connection() queued a message under sock_mut and then armed the libevent read/write event through the *_ul helpers, which unlock sock_mut, call event_add(), and re-lock. That temporary unlock opens a race window: the tcp worker can run on_read()/on_write() (and close()) on the same socket while send() believes it still holds the lock, so send() may resume operating on a connection that has just been torn down. event_add() does not call back into our handlers synchronously and only takes libevent's own event-base lock, so it is safe to arm the event while holding sock_mut. Use the non-unlocking add_read_event()/add_write_event() variants so the socket state stays consistent for the whole critical section. No lock ordering is introduced: close() already takes sock_mut before event_del(). Backport of the fix from yeti-switch/sems (commit 596150a0, Michael Furmur). sems-server's transport code matches the pre-fix version, so the same race is present here. --- core/sip/tcp_trsp.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/core/sip/tcp_trsp.cpp b/core/sip/tcp_trsp.cpp index fa38938fa..e07f2a98f 100644 --- a/core/sip/tcp_trsp.cpp +++ b/core/sip/tcp_trsp.cpp @@ -238,18 +238,16 @@ int tcp_trsp_socket::check_connection() create_events(); if(ret < 0) { - add_write_event_ul(server_sock->get_connect_timeout()); + add_write_event(server_sock->get_connect_timeout()); DBG("connect event added..."); - // because of unlock in ad_write_event_ul, - // on_connect() might already have been scheduled if(closed) return -1; } else { // connect succeeded immediatly connected = true; - add_read_event_ul(); + add_read_event(); } } @@ -267,7 +265,7 @@ int tcp_trsp_socket::send(const sockaddr_storage* sa, const char* msg, send_q.push_back(new msg_buf(sa,msg,msg_len)); if(connected) { - add_write_event_ul(); + add_write_event(); DBG("write event added..."); }