From e5fde7b55f55f3074cf453d1018cadc864030ef5 Mon Sep 17 00:00:00 2001 From: Rongsong Shen Date: Wed, 20 May 2026 09:39:07 +0000 Subject: [PATCH] fix(persist): zero nresvals_to_sched after free_name_val_list Crash: encode_NameValue_list called with count=21, s=NULL on worker rejoin, causing SIGSEGV in persist_worker_hook_fun. Root cause: free_name_val_list(xce_name_val_t***, int) accepted count by value. It zeroed *vals (resvals_to_sched = NULL) but could not zero nresvals_to_sched. Any caller that freed the scheduler resource snapshot (opget.c workerlist, reply.c clusterconf, dataex.c, sched.c dispatch) left nresvals_to_sched stale. When the worker later rejoined and the WAL HOOK fired, the WAL encoder read count=21 with a NULL pointer. Fix: change signature to free_name_val_list(xce_name_val_t***, int*) so both fields are zeroed atomically. Update all 7 call sites. --- src/controller/apiserver.c | 2 +- src/controller/dataex.c | 2 +- src/controller/opget.c | 2 +- src/controller/reply.c | 2 +- src/controller/sched.c | 6 +++--- src/include/utils.h | 2 +- src/lib/utils.c | 13 ++++++------- 7 files changed, 14 insertions(+), 15 deletions(-) diff --git a/src/controller/apiserver.c b/src/controller/apiserver.c index 73935500..1bd5b247 100644 --- a/src/controller/apiserver.c +++ b/src/controller/apiserver.c @@ -48,7 +48,7 @@ static int xce_apiserver_push_workers(cluster_t* c, endpoint_t* ep) for (i = 0; i < workers.n_total; i++) { xce_worker_t* w = workers.workers[i]; - free_name_val_list(&(w->resvals_to_sched), w->nresvals_to_sched); + free_name_val_list(&(w->resvals_to_sched), &(w->nresvals_to_sched)); } unlock_collect_workers(&wlist); diff --git a/src/controller/dataex.c b/src/controller/dataex.c index 02d35ed0..17183a67 100644 --- a/src/controller/dataex.c +++ b/src/controller/dataex.c @@ -417,7 +417,7 @@ void unlock_collect_workers(xlist_t* l) continue; } - free_name_val_list(&(w->resvals_to_sched), w->nresvals_to_sched); + free_name_val_list(&(w->resvals_to_sched), &(w->nresvals_to_sched)); w1 = CONTAINER_OF(w, worker_t, host); unlock(w1); diff --git a/src/controller/opget.c b/src/controller/opget.c index 7a3b1506..57c8f44e 100644 --- a/src/controller/opget.c +++ b/src/controller/opget.c @@ -125,7 +125,7 @@ static int do_reply_workerlist(cluster_t* c, endpoint_t* ep, for (i = 0; i < workerdata.n_total; i++) { xce_worker_t* w = workerdata.workers[i]; - free_name_val_list(&(w->resvals_to_sched), w->nresvals_to_sched); + free_name_val_list(&(w->resvals_to_sched), &(w->nresvals_to_sched)); } unlock_collect_workers(&wlist); diff --git a/src/controller/reply.c b/src/controller/reply.c index 79324435..eca10423 100644 --- a/src/controller/reply.c +++ b/src/controller/reply.c @@ -63,7 +63,7 @@ int handle_clusterconf(cluster_t* c, endpoint_t* ep, xce_request_t* request) for (i = 0; i < clusterconf.wlist.count; i++) { xce_worker_t* w = clusterconf.wlist.workers[i]; - free_name_val_list(&(w->resvals_to_sched), w->nresvals_to_sched); + free_name_val_list(&(w->resvals_to_sched), &(w->nresvals_to_sched)); } unlock_collect_queues(&qlist); diff --git a/src/controller/sched.c b/src/controller/sched.c index 3b741ac1..0b8d897f 100644 --- a/src/controller/sched.c +++ b/src/controller/sched.c @@ -143,7 +143,7 @@ static int xcesched_push_configs(cluster_t* c) rc = xce_pushconfig_req(c->sched.ep, c->myhost, &configdata); free_name_val_list(&(configdata.data.conf4sched->resvals), - configdata.data.conf4sched->nresvals); + &(configdata.data.conf4sched->nresvals)); FREEUP(configdata.data.conf4sched); @@ -223,7 +223,7 @@ static int xcesched_push_workers(cluster_t* c) for (i = 0; i < workers.n_total; i++) { xce_worker_t* w = workers.workers[i]; - free_name_val_list(&(w->resvals_to_sched), w->nresvals_to_sched); + free_name_val_list(&(w->resvals_to_sched), &(w->nresvals_to_sched)); } unlock_collect_workers(&wlist); @@ -461,7 +461,7 @@ static int sched_worker_change(int type, int situation, void* data, #if 0 /*FIXME*/ free_name_val_list(&(w->host.resvals_to_sched), - w->host.nresvals_to_sched); + &(w->host.nresvals_to_sched)); #endif xlist_fini(&resvalist); diff --git a/src/include/utils.h b/src/include/utils.h index 9b0306a3..a068ca09 100644 --- a/src/include/utils.h +++ b/src/include/utils.h @@ -127,7 +127,7 @@ extern xce_timewindow_config_t* dup_timewindow_config(xce_timewindow_config_t*); extern void free_resource_thresholds(xce_res_threshold_t**, int); extern xce_res_threshold_t** dup_resource_thresholds(xce_res_threshold_t**, int); -extern void free_name_val_list(xce_name_val_t***, int); +extern void free_name_val_list(xce_name_val_t***, int*); extern void free_strlist(xce_strlist_t*); extern int fmt_jobid_ex(char*, size_t, uint64_t, char*, char*); extern int fmt_jobid(char*, size_t, uint64_t); diff --git a/src/lib/utils.c b/src/lib/utils.c index 8d809309..da042e7b 100644 --- a/src/lib/utils.c +++ b/src/lib/utils.c @@ -385,16 +385,14 @@ int copy_strlist(xce_strlist_t* dst, xce_strlist_t src) } return 0; } -void free_name_val_list(xce_name_val_t*** vals, int count) +void free_name_val_list(xce_name_val_t*** vals, int *count_p) { xce_name_val_t** resvals = *vals; + int count = *count_p; int i; - if (resvals == NULL) { - return; - } - - if (count <= 0) { + if (resvals == NULL || count <= 0) { + *count_p = 0; return; } @@ -418,7 +416,8 @@ void free_name_val_list(xce_name_val_t*** vals, int count) } FREEUP(resvals); - *vals = NULL; + *vals = NULL; + *count_p = 0; } void free_strlist(xce_strlist_t* l)