Improve error handling and resource cleanup in ACLK query execution (#21479)
* Improve error handling and resource cleanup in ACLK query execution - Refine logic to handle resource cleanup when queueing commands fails. - Fix potential resource leaks by ensuring proper memory deallocation in failure paths. - Simplify and align conditional checks for better readability and maintainability. - Minor adjustments to redundant logging and error reporting. * Fix query batch count decrement during ACLK query cleanup
Stelios Fragkakis committed
Dec 18, 2025 at 19:56 UTC
7eaf10d19077abfa9e1fca276750c649e3baec4c
1 file changed
+49
-26
src/database/sqlite/sqlite_aclk.c
+49
-26
@@ -167,18 +167,19 @@ static int create_host_callback(void *data, int argc, char **argv, char **column
167
168
rrdhost_system_info_free(system_info);
169
170
- if (likely(host)) {
171
- if (is_ephemeral)
172
- rrdhost_option_set(host, RRDHOST_OPTION_EPHEMERAL_HOST);
170
+ if (unlikely(!host))
171
+ return 0;
172
174
- if (is_ephemeral)
175
- host->stream.rcv.status.last_disconnected = now_realtime_sec();
173
+ if (is_ephemeral)
174
+ rrdhost_option_set(host, RRDHOST_OPTION_EPHEMERAL_HOST);
175
177
- host->rrdlabels = sql_load_host_labels((nd_uuid_t *)argv[IDX_HOST_ID]);
178
- host->stream.snd.status.last_connected = last_connected;
176
+ if (is_ephemeral)
177
+ host->stream.rcv.status.last_disconnected = now_realtime_sec();
178
180
- pulse_host_status(host, 0, 0); // this will detect the receiver status
181
- }
179
+ host->rrdlabels = sql_load_host_labels((nd_uuid_t *)argv[IDX_HOST_ID]);
180
+ host->stream.snd.status.last_connected = last_connected;
181
+
182
+ pulse_host_status(host, 0, 0); // this will detect the receiver status
183
184
if (IS_VIRTUAL_HOST_OS(host))
185
node_data->vnodes++;
@@ -320,6 +321,7 @@ static void aclk_run_query(struct aclk_sync_config_s *config, aclk_query_t *quer
321
{
322
if (query->type == UNKNOWN || query->type >= ACLK_QUERY_TYPE_COUNT) {
323
error_report("Unknown query in query queue. %u", query->type);
324
+ aclk_query_free(query);
325
return;
326
}
327
@@ -440,9 +442,6 @@ static void aclk_execute_batch(uv_work_t *req)
442
if (!aclk_query_batch)
443
return;
444
443
- usec_t started_ut = now_monotonic_usec(); (void)started_ut;
444
-
445
- size_t entries = aclk_query_batch->count;
445
Word_t Index = 0;
446
bool first = true;
447
Pvoid_t *Pvalue;
@@ -457,11 +456,6 @@ static void aclk_execute_batch(uv_work_t *req)
456
(void) JudyLFreeArray(&aclk_query_batch->JudyL, PJE0);
457
freez(aclk_query_batch);
458
460
- usec_t ended_ut = now_monotonic_usec();
461
- (void)ended_ut;
462
- nd_log_daemon(
463
- NDLP_DEBUG, "Processed %zu ACLK commands in %0.2f ms", entries, (double)(ended_ut - started_ut) / USEC_PER_MS);
464
-
459
worker_is_idle();
460
}
461
@@ -729,7 +723,7 @@ static void aclk_synchronization_event_loop(void *arg)
723
create_aclk_config(host, &host->host_id.uuid, &host->node_id.uuid);
724
aclk_host_config = host->aclk_host_config;
725
}
732
- aclk_host_config->node_info_send_time = (host == localhost ||(void *)(uintptr_t) immediate) ? 1 : now_realtime_sec();
726
+ aclk_host_config->node_info_send_time = (host == localhost || immediate) ? 1 : now_realtime_sec();
727
break;
728
case ACLK_CANCEL_NODE_UPDATE_TIMER:
729
host = cmd.param[0];
@@ -786,8 +780,10 @@ static void aclk_synchronization_event_loop(void *arg)
780
if (Pvalue != PJERR) {
781
*Pvalue = query;
782
pending_queries++;
789
- } else
783
+ } else {
784
nd_log_daemon(NDLP_ERR, "Failed to add ACLK command to the pending commands Judy");
785
+ aclk_query_free(query);
786
+ }
787
break;
788
}
789
@@ -831,8 +827,10 @@ static void aclk_synchronization_event_loop(void *arg)
827
*Pvalue = query;
828
pending_queries++;
829
}
834
- else
830
+ else {
831
nd_log_daemon(NDLP_ERR, "Failed to add ACLK command to the pending commands Judy");
832
+ aclk_query_free(query);
833
+ }
834
}
835
break;
836
@@ -846,8 +844,13 @@ static void aclk_synchronization_event_loop(void *arg)
844
aclk_query_batch = callocz(1, sizeof(*aclk_query_batch));
845
846
Pvalue = JudyLIns(&aclk_query_batch->JudyL, ++aclk_query_batch->count, PJE0);
849
- if (Pvalue)
847
+ if (Pvalue != PJERR)
848
*Pvalue = query;
849
+ else {
850
+ aclk_query_free(query);
851
+ aclk_query_batch->count--;
852
+ break;
853
+ }
854
855
config->aclk_jobs_pending++;
856
if (aclk_query_batch->count < MAX_ACLK_BATCH_JOBS_IN_QUEUE || config->aclk_batch_job_is_running)
@@ -891,7 +894,7 @@ static void aclk_synchronization_event_loop(void *arg)
894
uv_close((uv_handle_t *)&config->timer_req, NULL);
895
896
uv_close((uv_handle_t *)&config->async, NULL);
894
- uv_walk(loop, libuv_close_callback, notify_timer_close_callback);
897
+ uv_walk(loop, libuv_close_callback, NULL);
898
899
size_t loop_count = (MAX_SHUTDOWN_TIMEOUT_SECONDS * MSEC_PER_SEC) / SHUTDOWN_SLEEP_INTERVAL_MS;
900
@@ -1084,7 +1087,14 @@ void aclk_push_alert_config(const char *node_id, const char *config_hash)
1087
if (unlikely(!node_id || !config_hash))
1088
return;
1089
1087
- queue_aclk_sync_cmd(ACLK_DATABASE_PUSH_ALERT_CONFIG, strdupz(node_id), strdupz(config_hash));
1090
+ char *node_id_dup = strdupz(node_id);
1091
+ char *config_hash_dup = strdupz(config_hash);
1092
+ bool queued = queue_aclk_sync_cmd(ACLK_DATABASE_PUSH_ALERT_CONFIG, node_id_dup, config_hash_dup);
1093
+ if (unlikely(!queued)) {
1094
+ nd_log_daemon(NDLP_WARNING, "ACLK: Failed to queue alert config push for node %s (config hash %s)", node_id, config_hash);
1095
+ freez(node_id_dup);
1096
+ freez(config_hash_dup);
1097
+ }
1098
}
1099
1100
void aclk_execute_query(aclk_query_t *query)
@@ -1092,7 +1102,11 @@ void aclk_execute_query(aclk_query_t *query)
1102
if (unlikely(!query))
1103
return;
1104
1095
- (void) queue_aclk_sync_cmd(ACLK_QUERY_EXECUTE, query, NULL);
1105
+ bool queued = queue_aclk_sync_cmd(ACLK_QUERY_EXECUTE, query, NULL);
1106
+ if (unlikely(!queued)) {
1107
+ nd_log_daemon(NDLP_WARNING, "ACLK: Failed to queue query execution");
1108
+ aclk_query_free(query);
1109
+ }
1110
}
1111
1112
void aclk_add_job(aclk_query_t *query)
@@ -1100,7 +1114,11 @@ void aclk_add_job(aclk_query_t *query)
1114
if (unlikely(!query))
1115
return;
1116
1103
- (void) queue_aclk_sync_cmd(ACLK_QUERY_BATCH_ADD, query, NULL);
1117
+ bool queued = queue_aclk_sync_cmd(ACLK_QUERY_BATCH_ADD, query, NULL);
1118
+ if (unlikely(!queued)) {
1119
+ nd_log_daemon(NDLP_WARNING, "ACLK: Failed to queue query job");
1120
+ aclk_query_free(query);
1121
+ }
1122
}
1123
1124
void aclk_mqtt_client_set(mqtt_wss_client client)
@@ -1133,7 +1151,12 @@ void unregister_node(const char *machine_guid)
1151
if (unlikely(!machine_guid))
1152
return;
1153
1136
- (void) queue_aclk_sync_cmd(ACLK_DATABASE_NODE_UNREGISTER, strdupz(machine_guid), NULL);
1154
+ char *machine_guid_dup = strdupz(machine_guid);
1155
+ bool queued = queue_aclk_sync_cmd(ACLK_DATABASE_NODE_UNREGISTER, machine_guid_dup, NULL);
1156
+ if (unlikely(!queued)) {
1157
+ nd_log_daemon(NDLP_WARNING, "ACLK: Failed to queue unregister node command for %s", machine_guid);
1158
+ freez(machine_guid_dup);
1159
+ }
1160
}
1161
1162
void destroy_aclk_config(RRDHOST *host)