diff --git a/src/scheduler/src/scheduler.c b/src/scheduler/src/scheduler.c index 8ca1c5e3..4a38978d 100644 --- a/src/scheduler/src/scheduler.c +++ b/src/scheduler/src/scheduler.c @@ -740,8 +740,48 @@ static int sched_update_workers(xce_scheduler_t* sched, int nworkers, for (i = 0; i < nworkers; i++) { xce_sched_worker_t* w = make_sched_worker(sched, workers[i]); + if (w == NULL) { + continue; + } plugin_worker_update(sched, w); + + /* bug-1494 (controller-restart self-heal): a re-push of an already + * known worker (e.g. after it rejoined with fresh resvals) must + * UPDATE it in place. key_add() would EEXIST-drop the fresh worker + * and leave the stale resvals in place — the scheduler keeps the + * dead/absent state (slots=0) and PEND jobs never dispatch even after + * the worker comes back with full capacity. Swap the fresh + * resvals/status into the existing worker, then discard the new + * object (which now holds the stale arrays). */ + xce_sched_worker_t* existing = sched_get_worker(sched, w->name); + if (existing != NULL) { + zarray_t tmp; + + tmp = existing->resvals; + existing->resvals = w->resvals; + w->resvals = tmp; + + tmp = existing->resInUse; + existing->resInUse = w->resInUse; + w->resInUse = tmp; + + existing->status = w->status; + + if (existing->host_eval_ctx != NULL) { + sched_worker_release_host_ctx(existing); + } + existing->host_eval_ctx = w->host_eval_ctx; + w->host_eval_ctx = NULL; + + zarray_fini(&(w->resvals)); + zarray_fini(&(w->resInUse)); + /* w->name is an interned string (makeString) owned by the + * xstring table — never free() it (bad-free). */ + free(w); + continue; + } + sched_add_worker(sched, w); }