Fix: Remove usleep from event loops and fix segfault in tests

- Removed usleep(5000) from all test event loops
- Changed to use single shared uasync for server and client instances
- Removed uasync_destroy from utun_instance_destroy to prevent double-free
- Added explicit uasync_destroy calls in all tests and main program
- Fixed segfault in test_pkt_normalizer_etcp and test_etcp_100_packets
- Added DEBUG_TRACE to all functions in etcp.c and etcp_connections.c

Tests now run without artificial delays and complete successfully.
This commit is contained in:
Evgeny committed 2026-02-05 20:51:07 +03:00
1 parent 8a3f01fbf8
commit beafb9b198
20 files changed
+599 -251

No files matched your search

+67 -51
View File
@@ -36,9 +36,10 @@ static void input_send_q_cb(struct ll_queue* q, void* arg);
static void wait_ack_cb(struct ll_queue* q, void* arg);
static void etcp_conn_process_send_queue(struct ETCP_CONN* etcp);
// Get current time in 0.1ms units
uint64_t get_current_time_units() {
struct timeval tv;
// Get current time in 0.1ms units
uint64_t get_current_time_units() {
DEBUG_TRACE(DEBUG_CATEGORY_ETCP, "");
struct timeval tv;
gettimeofday(&tv, NULL);
uint64_t time_units = ((uint64_t)tv.tv_sec * 10000ULL) + (tv.tv_usec / 100);
// DEBUG_TRACE(DEBUG_CATEGORY_ETCP, "get_current_time_units: tv_sec=%ld, tv_usec=%ld, result=%llu",
@@ -46,24 +47,26 @@ uint64_t get_current_time_units() {
return time_units;
}
uint16_t get_current_timestamp() {
uint16_t timestamp = (uint16_t)(get_current_time_units() & 0xFFFF);
uint16_t get_current_timestamp() {
DEBUG_TRACE(DEBUG_CATEGORY_ETCP, "");
uint16_t timestamp = (uint16_t)(get_current_time_units() & 0xFFFF);
// DEBUG_TRACE(DEBUG_CATEGORY_ETCP, "get_current_timestamp: result=%u", timestamp);
return timestamp;
}
// Timestamp diff (with wrap-around)
static uint16_t timestamp_diff(uint16_t t1, uint16_t t2) {
// DEBUG_TRACE(DEBUG_CATEGORY_ETCP, "timestamp_diff: t1=%u, t2=%u", t1, t2);
if (t1 >= t2) {
// Timestamp diff (with wrap-around)
static uint16_t timestamp_diff(uint16_t t1, uint16_t t2) {
DEBUG_TRACE(DEBUG_CATEGORY_ETCP, "");
if (t1 >= t2) {
return t1 - t2;
}
return (UINT16_MAX - t2) + t1 + 1;
}
// Create new ETCP connection
struct ETCP_CONN* etcp_connection_create(struct UTUN_INSTANCE* instance) {
if (!instance) return NULL;
// Create new ETCP connection
struct ETCP_CONN* etcp_connection_create(struct UTUN_INSTANCE* instance) {
DEBUG_TRACE(DEBUG_CATEGORY_ETCP, "");
if (!instance) return NULL;
struct ETCP_CONN* etcp = calloc(1, sizeof(struct ETCP_CONN));
@@ -122,9 +125,10 @@ struct ETCP_CONN* etcp_connection_create(struct UTUN_INSTANCE* instance) {
return etcp;
}
// Close connection with NULL pointer safety (prevents double free)
void etcp_connection_close(struct ETCP_CONN* etcp) {
if (!etcp) return;
// Close connection with NULL pointer safety (prevents double free)
void etcp_connection_close(struct ETCP_CONN* etcp) {
DEBUG_TRACE(DEBUG_CATEGORY_ETCP, "");
if (!etcp) return;
// Drain and free input_queue (contains ETCP_FRAGMENT with pkt_data from data_pool)
if (etcp->input_queue) {
@@ -232,6 +236,7 @@ void etcp_connection_close(struct ETCP_CONN* etcp) {
// Reset connection (stub)
void etcp_conn_reset(struct ETCP_CONN* etcp) {
DEBUG_TRACE(DEBUG_CATEGORY_ETCP, "");
// Reset IDs, queues, etc. as per protocol.txt
etcp->next_tx_id = 1;
etcp->last_rx_id = 0;
@@ -241,6 +246,7 @@ void etcp_conn_reset(struct ETCP_CONN* etcp) {
// Update log_name when peer_node_id becomes known
void etcp_update_log_name(struct ETCP_CONN* etcp) {
DEBUG_TRACE(DEBUG_CATEGORY_ETCP, "");
if (!etcp || !etcp->instance) return;
uint64_t local_id = etcp->instance->node_id % 10000;
uint64_t peer_id = etcp->peer_node_id % 10000;
@@ -251,11 +257,11 @@ void etcp_update_log_name(struct ETCP_CONN* etcp) {
// ====================================================================== Отправка данных
// Send data through ETCP connection
// Allocates memory from data_pool and places in input queue
// Returns: 0 on success, -1 on failure
int etcp_send(struct ETCP_CONN* etcp, const void* data, uint16_t len) {
// DEBUG_TRACE(DEBUG_CATEGORY_ETCP, "etcp_send: ENTER etcp=%p, data=%p, len=%zu", etcp, data, len);
// Send data through ETCP connection
// Allocates memory from data_pool and places in input queue
// Returns: 0 on success, -1 on failure
int etcp_send(struct ETCP_CONN* etcp, const void* data, uint16_t len) {
DEBUG_TRACE(DEBUG_CATEGORY_ETCP, "");
if (!etcp || !data || len == 0) {
DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "[%s] invalid parameters (etcp=%p, data=%p, len=%zu)", etcp->log_name, etcp, data, len);
@@ -314,7 +320,7 @@ int etcp_send(struct ETCP_CONN* etcp, const void* data, uint16_t len) {
static void input_queue_try_resume(struct ETCP_CONN* etcp) {
DEBUG_TRACE(DEBUG_CATEGORY_ETCP, "[%s] ENTER etcp=%p", etcp->log_name, etcp);
DEBUG_TRACE(DEBUG_CATEGORY_ETCP, "");
// если размер input_wait_ack+input_send_q в байтах < optimal_inflight то resume сейчас.
size_t wait_ack_bytes = queue_total_bytes(etcp->input_wait_ack);
@@ -330,6 +336,7 @@ static void input_queue_try_resume(struct ETCP_CONN* etcp) {
}
void etcp_stats(struct ETCP_CONN* etcp) {
DEBUG_TRACE(DEBUG_CATEGORY_ETCP, "");
if (!etcp) return;
DEBUG_DEBUG(DEBUG_CATEGORY_ETCP, "[%s] stats for conn=%p:", etcp->log_name, etcp);
@@ -371,10 +378,10 @@ void etcp_stats(struct ETCP_CONN* etcp) {
DEBUG_DEBUG(DEBUG_CATEGORY_ETCP, "[%s] rx_ack_till: %u", etcp->log_name, etcp->rx_ack_till);
}
// Input callback for input_queue (добавление новых кодограмм в стек)
// input_queue -> input_send_q
static void input_queue_cb(struct ll_queue* q, void* arg) {
// Input callback for input_queue (добавление новых кодограмм в стек)
// input_queue -> input_send_q
static void input_queue_cb(struct ll_queue* q, void* arg) {
DEBUG_TRACE(DEBUG_CATEGORY_ETCP, "");
struct ETCP_CONN* etcp = (struct ETCP_CONN*)arg;
struct ETCP_FRAGMENT* in_pkt = (struct ETCP_FRAGMENT*)queue_data_get(q);
@@ -423,8 +430,9 @@ static void input_queue_cb(struct ll_queue* q, void* arg) {
}
static void input_send_q_cb(struct ll_queue* q, void* arg) {// etcp->input_send_q processing
struct ETCP_CONN* etcp=(struct ETCP_CONN*)arg;
static void input_send_q_cb(struct ll_queue* q, void* arg) {// etcp->input_send_q processing
DEBUG_TRACE(DEBUG_CATEGORY_ETCP, "");
struct ETCP_CONN* etcp=(struct ETCP_CONN*)arg;
// size_t send_q_bytes = queue_total_bytes(etcp->input_send_q);
// size_t send_q_pkts = queue_entry_count(etcp->input_send_q);
@@ -433,9 +441,10 @@ static void input_send_q_cb(struct ll_queue* q, void* arg) {// etcp->input_send_
}
static void ack_timeout_check(void* arg) {
struct ETCP_CONN* etcp = (struct ETCP_CONN*)arg;
uint64_t now = get_current_time_units();
static void ack_timeout_check(void* arg) {
DEBUG_TRACE(DEBUG_CATEGORY_ETCP, "");
struct ETCP_CONN* etcp = (struct ETCP_CONN*)arg;
uint64_t now = get_current_time_units();
uint64_t timeout = 1000;//(uint64_t)(etcp->rtt_avg_10 * RETRANS_K1) + (uint64_t)(etcp->jitter * RETRANS_K2);
// DEBUG_DEBUG(DEBUG_CATEGORY_ETCP, "ack_timeout_check: starting check, now=%llu, timeout=%llu, rtt_avg_10=%u, jitter=%u",
@@ -495,15 +504,16 @@ static void ack_timeout_check(void* arg) {
queue_resume_callback(etcp->input_wait_ack);
}
static void wait_ack_cb(struct ll_queue* q, void* arg) {
struct ETCP_CONN* etcp = (struct ETCP_CONN*)arg;
ack_timeout_check(etcp);// ack_cb срабатывает когда init (таймер не инициализирован) или когда empty (таймер не активен)
static void wait_ack_cb(struct ll_queue* q, void* arg) {
DEBUG_TRACE(DEBUG_CATEGORY_ETCP, "");
struct ETCP_CONN* etcp = (struct ETCP_CONN*)arg;
ack_timeout_check(etcp);// ack_cb срабатывает когда init (таймер не инициализирован) или когда empty (таймер не активен)
}
// Подготовить и отправить кодограмму
// вызывается линком когда освобождается или очередью если появляются данные на передачу
struct ETCP_DGRAM* etcp_request_pkt(struct ETCP_CONN* etcp) {
// Подготовить и отправить кодограмму
// вызывается линком когда освобождается или очередью если появляются данные на передачу
struct ETCP_DGRAM* etcp_request_pkt(struct ETCP_CONN* etcp) {
DEBUG_TRACE(DEBUG_CATEGORY_ETCP, "");
struct ETCP_LINK* link = etcp_loadbalancer_select_link(etcp);
if (!link) {
DEBUG_DEBUG(DEBUG_CATEGORY_ETCP, "[%s] no link available", etcp->log_name);
@@ -603,24 +613,27 @@ struct ETCP_DGRAM* etcp_request_pkt(struct ETCP_CONN* etcp) {
return dgram;
}
// Callback for when a link is ready to send data
static void etcp_link_ready_callback(struct ETCP_CONN* etcp) {
if (!etcp) return;
// Callback for when a link is ready to send data
static void etcp_link_ready_callback(struct ETCP_CONN* etcp) {
DEBUG_TRACE(DEBUG_CATEGORY_ETCP, "");
if (!etcp) return;
// DEBUG_DEBUG(DEBUG_CATEGORY_ETCP, "etcp_link_ready_callback: processing send queue for etcp=%p", etcp);
etcp_conn_process_send_queue(etcp);
}
// Process packets in send queue and transmit them
static void etcp_conn_process_send_queue(struct ETCP_CONN* etcp) {
struct ETCP_DGRAM* dgram;
// Process packets in send queue and transmit them
static void etcp_conn_process_send_queue(struct ETCP_CONN* etcp) {
DEBUG_TRACE(DEBUG_CATEGORY_ETCP, "");
struct ETCP_DGRAM* dgram;
while(dgram = etcp_request_pkt(etcp)) {
// DEBUG_DEBUG(DEBUG_CATEGORY_ETCP, "etcp_conn_process_send_queue: sending packet");
etcp_loadbalancer_send(dgram);
}
}
static void ack_response_timer_cb(void* arg) {// проверяем неотправленные ack response и отправляем если надо.
struct ETCP_CONN* etcp = (struct ETCP_CONN*)arg;
static void ack_response_timer_cb(void* arg) {// проверяем неотправленные ack response и отправляем если надо.
DEBUG_TRACE(DEBUG_CATEGORY_ETCP, "");
struct ETCP_CONN* etcp = (struct ETCP_CONN*)arg;
etcp_conn_process_send_queue(etcp);// проталкиваем (она же должна отправлять только ack если больше ничего нет)
// если ack все еще заняты - обновляем таймаут
if (etcp->ack_q->count) etcp->ack_resp_timer = uasync_set_timeout(etcp->instance->ua, ACK_DELAY_TB, etcp, ack_response_timer_cb);
@@ -631,6 +644,7 @@ static void ack_response_timer_cb(void* arg) {// проверяем неотпр
void etcp_output_try_assembly(struct ETCP_CONN* etcp) {
DEBUG_TRACE(DEBUG_CATEGORY_ETCP, "");
// пробуем собрать выходную очередь из фрагментов
// DEBUG_DEBUG(DEBUG_CATEGORY_ETCP, "[%s] etcp=%p, last_delivered_id=%u, recv_q_count=%d",
// etcp->log_name, etcp, etcp->last_delivered_id, queue_entry_count(etcp->recv_q));
@@ -678,9 +692,10 @@ void etcp_output_try_assembly(struct ETCP_CONN* etcp) {
etcp->log_name, delivered_count, delivered_bytes, etcp->last_delivered_id, queue_entry_count(etcp->output_queue));
}
// Process ACK receipt - remove acknowledged packet from inflight queues
void etcp_ack_recv(struct ETCP_CONN* etcp, uint32_t seq, uint16_t ts, uint16_t dts) {
if (!etcp) return;
// Process ACK receipt - remove acknowledged packet from inflight queues
void etcp_ack_recv(struct ETCP_CONN* etcp, uint32_t seq, uint16_t ts, uint16_t dts) {
DEBUG_TRACE(DEBUG_CATEGORY_ETCP, "");
if (!etcp) return;
// DEBUG_DEBUG(DEBUG_CATEGORY_ETCP, "[%s] processing ACK for seq=%u, ts=%u, dts=%u", etcp->log_name, seq, ts, dts);
@@ -747,9 +762,10 @@ void etcp_ack_recv(struct ETCP_CONN* etcp, uint32_t seq, uint16_t ts, uint16_t d
}
// Process incoming decrypted packet
void etcp_conn_input(struct ETCP_DGRAM* pkt) {
if (!pkt || !pkt->data_len) return;
// Process incoming decrypted packet
void etcp_conn_input(struct ETCP_DGRAM* pkt) {
DEBUG_TRACE(DEBUG_CATEGORY_ETCP, "");
if (!pkt || !pkt->data_len) return;
struct ETCP_CONN* etcp = pkt->link->etcp;
uint8_t* data = pkt->data;
+22
View File
@@ -24,6 +24,7 @@ static void etcp_link_remove_from_connections(struct ETCP_SOCKET* conn, struct E
// Unified packet dump function - uses configured format
static void packet_dump(const char* prefix, const uint8_t* data, size_t len, struct ETCP_LINK* link) {
DEBUG_TRACE(DEBUG_CATEGORY_CONNECTION, "");
if (!data || len == 0) return;
// Full multi-line format (legacy)
@@ -39,6 +40,7 @@ static void etcp_link_init_timer_cbk(void* arg);
#define INIT_TIMEOUT_MAX 50000
static void etcp_link_send_init(struct ETCP_LINK* link) {
DEBUG_TRACE(DEBUG_CATEGORY_CONNECTION, "");
DEBUG_INFO(DEBUG_CATEGORY_CONNECTION, "etcp_link_send_init link=%p, is_server=%d", link, link ? link->is_server : -1);
if (!link || !link->etcp || !link->etcp->instance) return;
@@ -104,6 +106,7 @@ static void etcp_link_send_init(struct ETCP_LINK* link) {
}
static void etcp_link_init_timer_cbk(void* arg) {
DEBUG_TRACE(DEBUG_CATEGORY_CONNECTION, "");
struct ETCP_LINK* link = (struct ETCP_LINK*)arg;
if (!link || link->initialized || link->is_server != 0) return;
@@ -112,6 +115,7 @@ static void etcp_link_init_timer_cbk(void* arg) {
}
static int etcp_link_send_reset(struct ETCP_LINK* link) {
DEBUG_TRACE(DEBUG_CATEGORY_CONNECTION, "");
if (!link) return -1;
struct ETCP_DGRAM* dgram = malloc(sizeof(struct ETCP_DGRAM) + 1);
@@ -132,12 +136,14 @@ static int etcp_link_send_reset(struct ETCP_LINK* link) {
}
static uint32_t sockaddr_hash(struct sockaddr_storage* addr) {
DEBUG_TRACE(DEBUG_CATEGORY_CONNECTION, "");
socklen_t addr_len = (addr->ss_family == AF_INET) ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6);
return crc32_calc((void*)addr, addr_len);
}
// Бинарный поиск линка по ip_port_hash
static int find_link_index(struct ETCP_SOCKET* e_sock, uint32_t hash) {
DEBUG_TRACE(DEBUG_CATEGORY_CONNECTION, "");
if (!e_sock || e_sock->num_channels == 0) return -1;
int left = 0;
@@ -159,6 +165,7 @@ static int find_link_index(struct ETCP_SOCKET* e_sock, uint32_t hash) {
// Реалокация массива линков с увеличением в 2 раза
static int realloc_links(struct ETCP_SOCKET* e_sock) {
DEBUG_TRACE(DEBUG_CATEGORY_CONNECTION, "");
size_t new_max = e_sock->max_channels == 0 ? 8 : e_sock->max_channels * 2;
struct ETCP_LINK** new_links = realloc(e_sock->links, new_max * sizeof(struct ETCP_LINK*));
if (!new_links) {
@@ -173,6 +180,7 @@ static int realloc_links(struct ETCP_SOCKET* e_sock) {
// Вставка линка в отсортированный массив
static int insert_link(struct ETCP_SOCKET* e_sock, struct ETCP_LINK* link) {
DEBUG_TRACE(DEBUG_CATEGORY_CONNECTION, "");
if (!e_sock || !link) return -1;
if (e_sock->num_channels >= e_sock->max_channels) {
@@ -196,6 +204,7 @@ static int insert_link(struct ETCP_SOCKET* e_sock, struct ETCP_LINK* link) {
// Удаление линка из массива
static void remove_link(struct ETCP_SOCKET* e_sock, uint32_t hash) {
DEBUG_TRACE(DEBUG_CATEGORY_CONNECTION, "");
if (!e_sock || e_sock->num_channels == 0) return;
int idx = find_link_index(e_sock, hash);
@@ -211,6 +220,7 @@ static void remove_link(struct ETCP_SOCKET* e_sock, uint32_t hash) {
// надо править, используй sockaddr_hash
struct ETCP_LINK* etcp_link_find_by_addr(struct ETCP_SOCKET* e_sock, struct sockaddr_storage* addr) {
DEBUG_TRACE(DEBUG_CATEGORY_CONNECTION, "");
if (!e_sock || !addr) return NULL;
int idx = find_link_index(e_sock, sockaddr_hash(addr));
@@ -220,6 +230,7 @@ struct ETCP_LINK* etcp_link_find_by_addr(struct ETCP_SOCKET* e_sock, struct sock
}
int etcp_find_free_local_link_id(struct ETCP_CONN* etcp) {
DEBUG_TRACE(DEBUG_CATEGORY_CONNECTION, "");
if (!etcp) return -1;
// Битовый массив для 256 id (32 байта * 8 бит = 256)
@@ -254,6 +265,7 @@ int etcp_find_free_local_link_id(struct ETCP_CONN* etcp) {
// ===============================
struct ETCP_SOCKET* etcp_socket_add(struct UTUN_INSTANCE* instance, struct sockaddr_storage* ip, uint32_t netif_index, int so_mark, uint8_t type) {
DEBUG_TRACE(DEBUG_CATEGORY_CONNECTION, "");
if (!instance) return NULL;
struct ETCP_SOCKET* e_sock = calloc(1, sizeof(struct ETCP_SOCKET));
@@ -368,6 +380,7 @@ struct ETCP_SOCKET* etcp_socket_add(struct UTUN_INSTANCE* instance, struct socka
}
void etcp_socket_remove(struct ETCP_SOCKET* conn) {
DEBUG_TRACE(DEBUG_CATEGORY_CONNECTION, "");
if (!conn) return;
DEBUG_INFO(DEBUG_CATEGORY_ETCP, "[ETCP] Removing socket %p, fd=%d, socket_id=%p", conn, conn->fd, conn->socket_id);
@@ -395,6 +408,7 @@ void etcp_socket_remove(struct ETCP_SOCKET* conn) {
struct ETCP_LINK* etcp_link_new(struct ETCP_CONN* etcp, struct ETCP_SOCKET* conn, struct sockaddr_storage* remote_addr, uint8_t is_server) {
DEBUG_TRACE(DEBUG_CATEGORY_CONNECTION, "");
if (!remote_addr) return NULL;
struct ETCP_LINK* link = calloc(1, sizeof(struct ETCP_LINK));
@@ -442,6 +456,7 @@ struct ETCP_LINK* etcp_link_new(struct ETCP_CONN* etcp, struct ETCP_SOCKET* conn
}
void etcp_link_close(struct ETCP_LINK* link) {
DEBUG_TRACE(DEBUG_CATEGORY_CONNECTION, "");
if (!link || !link->etcp) return;
// Cancel init timer if active
@@ -466,6 +481,7 @@ void etcp_link_close(struct ETCP_LINK* link) {
}
int etcp_encrypt_send(struct ETCP_DGRAM* dgram) {
DEBUG_TRACE(DEBUG_CATEGORY_CONNECTION, "");
// DEBUG_DEBUG(DEBUG_CATEGORY_ETCP, "etcp_encrypt_send called, link=%p", dgram ? dgram->link : NULL);
// printf("[ETCP DEBUG] etcp_encrypt_send: ENTERING FUNCTION\n");
@@ -479,7 +495,9 @@ int etcp_encrypt_send(struct ETCP_DGRAM* dgram) {
// DUMP: Show packet before encryption
// log_dump("ECTP_ENCRYPT_SEND", dgram->data, dgram->data_len);
DEBUG_INFO(DEBUG_CATEGORY_ETCP, "Encrypt start");
sc_encrypt(sc, (uint8_t*)&dgram->timestamp/*не править это, тут верно!*/, sizeof(uint16_t) + len, enc_buf, &enc_buf_len);
DEBUG_INFO(DEBUG_CATEGORY_ETCP, "Encrypt end");
if (enc_buf_len == 0) {
DEBUG_ERROR(DEBUG_CATEGORY_CRYPTO, "etcp_encrypt_send: encryption failed for node %llu", (unsigned long long)dgram->link->etcp->instance->node_id);
dgram->link->send_errors++;
@@ -518,6 +536,7 @@ es_err:
}
static void etcp_connections_read_callback(int fd, void* arg) {
DEBUG_TRACE(DEBUG_CATEGORY_CONNECTION, "");
// DEBUG_DEBUG(DEBUG_CATEGORY_ETCP, "etcp_connections_read_callback fd=%d, socket=%p", fd, arg);
// !!!!!! DANGER: в этой функции ПРЕДЕЛЬНАЯ АККУРАТНОСТЬ. Если кажется что не туда указатель то невнимательно аланизировал !!!!!
// НЕ РУИНИТЬ (uint8_t*)&pkt->timestamp - это правильно !!!!
@@ -652,6 +671,7 @@ static void etcp_connections_read_callback(int fd, void* arg) {
return;
}
DEBUG_INFO(DEBUG_CATEGORY_ETCP, "Decrypt start");
if (sc_decrypt(&link->etcp->crypto_ctx, data, recv_len, (uint8_t*)&pkt->timestamp, &pkt_len)) {
DEBUG_ERROR(DEBUG_CATEGORY_CRYPTO, "etcp_connections_read_callback: failed to decrypt packet from node %llu len=%d", (unsigned long long)link->etcp->instance->node_id, recv_len);
// log_dump("my_privkey",&link->etcp->crypto_ctx.pk->private_key, SC_PRIVKEY_SIZE);
@@ -660,6 +680,7 @@ static void etcp_connections_read_callback(int fd, void* arg) {
errorcode=6;
goto ec_fr;
}
DEBUG_INFO(DEBUG_CATEGORY_ETCP, "Decrypt end");
if (pkt_len<3) { errorcode=46; DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "etcp_connections_read_callback: decrypted packet too small, size=%zu", pkt_len); goto ec_fr; }
pkt->data_len=pkt_len-2;
pkt->noencrypt_len=0;
@@ -718,6 +739,7 @@ ec_fr:
}
int init_connections(struct UTUN_INSTANCE* instance) {
DEBUG_TRACE(DEBUG_CATEGORY_CONNECTION, "");
if (!instance || !instance->config) return -1;
struct utun_config* config = instance->config;
+7 -1
View File
@@ -326,7 +326,13 @@ int main(int argc, char *argv[]) {
utun_instance_unregister_sockets(instance);
utun_instance_destroy(instance);
// Destroy uasync instance after instance is destroyed
if (ua) {
uasync_destroy(ua, 0);
}
remove_pidfile(args.pid_file);
return 0;
}
+3 -6
View File
@@ -227,12 +227,9 @@ void utun_instance_destroy(struct UTUN_INSTANCE *instance) {
instance->data_pool = NULL;
}
// FINALLY destroy uasync (after all resources are cleaned up)
if (instance->ua) {
DEBUG_INFO(DEBUG_CATEGORY_MEMORY, "[INSTANCE_DESTROY] Destroying uasync instance");
uasync_destroy(instance->ua, 0);
instance->ua = NULL;
}
// Note: uasync is NOT destroyed here - caller must destroy it separately
// This allows sharing uasync between multiple instances
instance->ua = NULL;
// Clear global instance
if (g_instance == instance) {