Coalesce useful TX wakeups and defer failure teardown safely

This commit is contained in:
evgeny committed 2026-10-22 22:45:58 +02:00
1 parent f1c88ad375
commit 0ef0553598
2 files changed
+13 -1

No files matched your search

+12 -1
View File
@@ -50,17 +50,28 @@ static void send_ack_req_cb(struct ll_queue* q, void* arg);
static void etcp_conn_process_send_queue(struct ETCP_CONN* etcp);
static void etcp_send_timer_cb(void* arg);
static void etcp_connection_free_deferred(void* arg);
static void etcp_connection_close_deferred(void* arg);
void etcp_fire_conn_status(struct ETCP_CONN* etcp, int status);
struct ETCP_DGRAM* etcp_request_pkt(struct ETCP_CONN* etcp);
/* Очереди и сетевые события только планируют проход: синхронные callbacks не входят в отправитель повторно. */
static void etcp_schedule_send(struct ETCP_CONN* conn, int delay_tb) {
if (!conn || conn->close_requested || conn->state == 2 || conn->tx_timer) return;
if (!conn->initialized || conn->session_required || conn->reinit_pending) return;
if (conn->tx_running && delay_tb == 1) return;
int work = conn->input_send_q->count || conn->input_queue->count || conn->ack_q->count;
for (struct ETCP_LINK* link = conn->links; !work && link; link = link->next) work = link->burst_active;
if (!work) return;
conn->tx_timer = uasync_set_timeout(conn->instance->ua, delay_tb, conn, etcp_send_timer_cb, "etcp_tx");
if (!conn->tx_timer) {
DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "[%s] cannot schedule sender delay=%d", conn->log_name, delay_tb);
etcp_connection_close(conn);
// Вызывающий может ещё собирать линк/менять очередь: ресурсы освобождаются после выхода из его стека.
conn->close_requested = 1;
conn->close_token = uasync_call_soon(conn->instance->ua, conn, etcp_connection_close_deferred);
if (!conn->close_token) {
DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "[%s] cannot defer mandatory close after TX timer failure", conn->log_name);
abort();
}
}
}
+1
View File
@@ -247,6 +247,7 @@ static void pacing_reset_close(void) {
enqueue(100); CHECK(conn->tx_timer);
etcp_conn_reinit_id(conn, "queued sender reset", conn->reset_id);
CHECK(!conn->tx_timer && !conn->unacked_bytes && conn->reinit_pending);
etcp_conn_ready(conn);
enqueue(100); CHECK(conn->tx_timer);
CHECK(etcp_conn_ref_take(conn) == 0);
etcp_connection_close(conn); CHECK(conn->state == 2 && !conn->tx_timer);