diff --git a/src/etcp.c b/src/etcp.c index 6b1a3b2e..b31d82be 100644 --- a/src/etcp.c +++ b/src/etcp.c @@ -216,6 +216,7 @@ struct ETCP_CONN* etcp_connection_create(struct UTUN_INSTANCE* instance, char* n etcp->initialized=0; etcp->links_up=0; etcp->reset_done=0; + etcp->callbacks_running=0; etcp->last_rr_link=NULL; etcp->name = u_strdup(name); // Initialize log_name with local node_id (peer will be updated later when known) @@ -270,14 +271,18 @@ struct ETCP_CONN* etcp_connection_create(struct UTUN_INSTANCE* instance, char* n static void etcp_on_up(struct ETCP_CONN* etcp) { DEBUG_WARN(DEBUG_CATEGORY_BGP, "[%s] UP links_up=%d initialized=%d", etcp->log_name, etcp->links_up, etcp->initialized); + etcp->callbacks_running = 1; struct etcp_cbk_entry* cbe = etcp->up_cbks; while (cbe) { struct etcp_cbk_entry* n = cbe->next; cbe->fn(etcp, cbe->arg); cbe = n; } + etcp->callbacks_running = 0; } static void etcp_on_down(struct ETCP_CONN* etcp) { DEBUG_WARN(DEBUG_CATEGORY_BGP, "[%s] DOWN links_up=%d", etcp->log_name, etcp->links_up); + etcp->callbacks_running = 1; struct etcp_cbk_entry* cbe = etcp->down_cbks; while (cbe) { struct etcp_cbk_entry* n = cbe->next; cbe->fn(etcp, cbe->arg); cbe = n; } + etcp->callbacks_running = 0; } @@ -286,6 +291,12 @@ void etcp_connection_close(struct ETCP_CONN* etcp) { DEBUG_TRACE(DEBUG_CATEGORY_ETCP, ""); if (!etcp) return; + if (etcp->callbacks_running) { + DEBUG_ERROR(DEBUG_CATEGORY_DEBUG, "[%s] FATAL: etcp_connection_close called from inside callback chain — SEGFAULTING to show backtrace", + etcp->log_name); + *(volatile int*)0 = 0; + } + if (etcp->links_up!=0) { etcp->links_up=0; etcp_on_down(etcp); @@ -541,8 +552,10 @@ void etcp_conn_ready(struct ETCP_CONN* conn) { etcp_metrics_start_timer(conn); // Вызываем callback если установлен + conn->callbacks_running = 1; { struct etcp_cbk_entry* cbe = conn->ready_cbks; while (cbe) { struct etcp_cbk_entry* n = cbe->next; cbe->fn(conn, cbe->arg); cbe = n; } } if (conn->links_up) etcp_on_up(conn); + conn->callbacks_running = 0; } diff --git a/src/etcp.h b/src/etcp.h index de6ca971..0b3b7faa 100644 --- a/src/etcp.h +++ b/src/etcp.h @@ -226,6 +226,7 @@ struct ETCP_CONN { uint8_t tx_state; // 0 - n/a, 1 - data_wait (queues empty), 2 - link_wait (link busy) uint8_t links_up; // 0 - канал не готов для передачи, 1 - канал готов для передачи (хотя бы один линк не down) uint8_t reset_done; // 0 - рукопожатие не завершено (реинит разрешён), 1 - соединение стабильно (реинит заблокирован) + uint8_t callbacks_running; // 1 - внутри итерации колбэк-цепочек, etcp_connection_close запрещён // Callback chains for ready/up/down notifications struct etcp_cbk_entry* ready_cbks; // цепочка callback'ов при готовности соединения