Fix memory leaks: drain all queues before freeing in etcp_connection_close()
- Added proper cleanup for all 6 queues in etcp_connection_close(): * input_queue: drain ETCP_FRAGMENT with pkt_data * output_queue: drain ETCP_FRAGMENT with pkt_data * input_send_q: drain INFLIGHT_PACKET with pkt_data * input_wait_ack: drain INFLIGHT_PACKET with pkt_data * ack_q: drain ACK_PACKET * recv_q: drain ETCP_FRAGMENT with pkt_data - Each element is properly freed with memory_pool_free before queue_free - Memory pools are destroyed after all elements returned - Result: 0 bytes leaked (was 12,864 bytes)
This commit is contained in:
1 parent
191de191d5
commit
043e1b58a6
2 files changed
+51
-2
No files matched your search
+51
-2
@@ -115,33 +115,82 @@ struct ETCP_CONN* etcp_connection_create(struct UTUN_INSTANCE* instance) {
|
|||||||
void etcp_connection_close(struct ETCP_CONN* etcp) {
|
void etcp_connection_close(struct ETCP_CONN* etcp) {
|
||||||
if (!etcp) return;
|
if (!etcp) return;
|
||||||
|
|
||||||
// Free queues only if they exist, then nullify to prevent double free
|
// Drain and free input_queue (contains ETCP_FRAGMENT with pkt_data from data_pool)
|
||||||
if (etcp->input_queue) {
|
if (etcp->input_queue) {
|
||||||
|
struct ETCP_FRAGMENT* pkt;
|
||||||
|
while ((pkt = queue_data_get(etcp->input_queue)) != NULL) {
|
||||||
|
if (pkt->pkt_data) {
|
||||||
|
memory_pool_free(etcp->instance->data_pool, pkt->pkt_data);
|
||||||
|
}
|
||||||
|
memory_pool_free(etcp->rx_pool, pkt);
|
||||||
|
}
|
||||||
queue_free(etcp->input_queue);
|
queue_free(etcp->input_queue);
|
||||||
etcp->input_queue = NULL;
|
etcp->input_queue = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Drain and free output_queue (contains ETCP_FRAGMENT with pkt_data from data_pool)
|
||||||
if (etcp->output_queue) {
|
if (etcp->output_queue) {
|
||||||
|
struct ETCP_FRAGMENT* pkt;
|
||||||
|
while ((pkt = queue_data_get(etcp->output_queue)) != NULL) {
|
||||||
|
if (pkt->pkt_data) {
|
||||||
|
memory_pool_free(etcp->instance->data_pool, pkt->pkt_data);
|
||||||
|
}
|
||||||
|
memory_pool_free(etcp->rx_pool, pkt);
|
||||||
|
}
|
||||||
queue_free(etcp->output_queue);
|
queue_free(etcp->output_queue);
|
||||||
etcp->output_queue = NULL;
|
etcp->output_queue = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Drain and free input_send_q (contains INFLIGHT_PACKET with pkt_data from data_pool)
|
||||||
if (etcp->input_send_q) {
|
if (etcp->input_send_q) {
|
||||||
|
struct INFLIGHT_PACKET* pkt;
|
||||||
|
while ((pkt = queue_data_get(etcp->input_send_q)) != NULL) {
|
||||||
|
if (pkt->pkt_data) {
|
||||||
|
memory_pool_free(etcp->instance->data_pool, pkt->pkt_data);
|
||||||
|
}
|
||||||
|
memory_pool_free(etcp->inflight_pool, pkt);
|
||||||
|
}
|
||||||
queue_free(etcp->input_send_q);
|
queue_free(etcp->input_send_q);
|
||||||
etcp->input_send_q = NULL;
|
etcp->input_send_q = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Drain and free input_wait_ack (contains INFLIGHT_PACKET with pkt_data from data_pool)
|
||||||
if (etcp->input_wait_ack) {
|
if (etcp->input_wait_ack) {
|
||||||
|
struct INFLIGHT_PACKET* pkt;
|
||||||
|
while ((pkt = queue_data_get(etcp->input_wait_ack)) != NULL) {
|
||||||
|
if (pkt->pkt_data) {
|
||||||
|
memory_pool_free(etcp->instance->data_pool, pkt->pkt_data);
|
||||||
|
}
|
||||||
|
memory_pool_free(etcp->inflight_pool, pkt);
|
||||||
|
}
|
||||||
queue_free(etcp->input_wait_ack);
|
queue_free(etcp->input_wait_ack);
|
||||||
etcp->input_wait_ack = NULL;
|
etcp->input_wait_ack = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Drain and free ack_q (contains ACK_PACKET from ack_pool)
|
||||||
if (etcp->ack_q) {
|
if (etcp->ack_q) {
|
||||||
|
struct ACK_PACKET* pkt;
|
||||||
|
while ((pkt = queue_data_get(etcp->ack_q)) != NULL) {
|
||||||
|
queue_data_free(pkt);
|
||||||
|
}
|
||||||
queue_free(etcp->ack_q);
|
queue_free(etcp->ack_q);
|
||||||
etcp->ack_q = NULL;
|
etcp->ack_q = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Drain and free recv_q (contains ETCP_FRAGMENT with pkt_data from data_pool)
|
||||||
if (etcp->recv_q) {
|
if (etcp->recv_q) {
|
||||||
|
struct ETCP_FRAGMENT* pkt;
|
||||||
|
while ((pkt = queue_data_get(etcp->recv_q)) != NULL) {
|
||||||
|
if (pkt->pkt_data) {
|
||||||
|
memory_pool_free(etcp->instance->data_pool, pkt->pkt_data);
|
||||||
|
}
|
||||||
|
memory_pool_free(etcp->rx_pool, pkt);
|
||||||
|
}
|
||||||
queue_free(etcp->recv_q);
|
queue_free(etcp->recv_q);
|
||||||
etcp->recv_q = NULL;
|
etcp->recv_q = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Free memory pool only if it exists
|
// Free memory pools after all elements are returned
|
||||||
if (etcp->inflight_pool) {
|
if (etcp->inflight_pool) {
|
||||||
memory_pool_destroy(etcp->inflight_pool);
|
memory_pool_destroy(etcp->inflight_pool);
|
||||||
etcp->inflight_pool = NULL;
|
etcp->inflight_pool = NULL;
|
||||||
|
|||||||
Binary file not shown.
Reference in new issue
Block a user