fix(worker): keep signals for remote tasks that are still starting (bug-1955)

Only a head-host job start opened the pending-signal window (bug-1908), so a
kill for a remote task of a multi-host job that this host had accepted
(runtasks) but not yet registered was dropped with "Failed to find worker".
handle_runtasks() now opens the same window before queuing the task and
closes it if queuing fails; the signal is delivered when the task runs.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Rongsong Shen 2026-10-10 09:10:13 +00:00
parent 148557a5d5
commit d3da314041
Signed by untrusted user: rshen
GPG key ID: 80533536B0EB651C
2 changed files with 49 additions and 0 deletions

View file

@ -1390,10 +1390,15 @@ static int handle_runtasks(xce_request_t* request)
task_ctx->xce_jobid = runmsg->jobid;
task_ctx->clientidx = runmsg->clientidx;
/* bug-1955: like a head-host start (bug-1908), from here until the
* task runs a signal for it is kept instead of being dropped */
pending_signal_start(runmsg->jobid);
if (submit_fork_task(cc_ctx->thread_pool, task_ctx) != 0) {
XCECD_LOG(XCE_LOG_ERROR, "Failed to add task to thread pool");
free_startinfo(task_ctx->startinfo);
FREEUP(task_ctx);
(void)pending_signal_take(runmsg->jobid, NULL, NULL);
xcecd_task_fail(runmsg->jobid, runmsg->clientidx, -1, -ENOMEM);
return -1;
} else {

View file

@ -1595,6 +1595,49 @@ static void test_jobcontrol_signal_for_unknown_job_fails(void)
TEST_ASSERT_EQUAL_INT(0, pending_signal_count());
}
/* bug-1955: a kill for a remote task this host accepted (runtasks) but has
* not registered yet is kept like a head-host start (bug-1908), not dropped
* with "Failed to find worker". */
static void test_jobcontrol_signal_for_queued_remote_task_is_kept(void)
{
controller_connector_ctx_t fake_cc = { 0 };
void* worker_list_head = NULL;
fake_cc.running = true;
fake_cc.worker_list = &worker_list_head;
cc_ctx = &fake_cc;
char host[] = "rt-host";
char cmd[] = "sleep 60";
char user[] = "nobody";
xce_taskhost_t th = { .host = host, .ntasks = 1, .execuser = user,
.cmdline = cmd };
xce_taskhost_t* ths[1] = { &th };
xce_taskrun_t run = { .jobid = 4545, .nhosts = 1, .clientidx = 0,
.taskhosts = ths };
xce_request_t runreq = { 0 };
xce_signal_t sig = { .signo = 9, .force = 1 };
xce_jobctrl_t ctrl = { .action = JobControl_u_siginfo, .jobid = 4545 };
xce_request_t sigreq = { 0 };
char* old_from = xce_client_cfg.from;
int signo = 0;
bool force = false;
xce_client_cfg.from = host;
runreq.body.runtaskmsg = &run;
TEST_ASSERT_EQUAL_INT(0, handle_runtasks(&runreq));
ctrl.u.siginfo = &sig;
sigreq.body.jobctrlmsg = &ctrl;
TEST_ASSERT_EQUAL_INT_MESSAGE(0, handle_jobcontrol(&sigreq),
"the kill must not be dropped");
TEST_ASSERT_TRUE_MESSAGE(pending_signal_take(4545, &signo, &force),
"the kill must be kept for the queued task");
TEST_ASSERT_EQUAL_INT(9, signo);
TEST_ASSERT_TRUE(force);
xce_client_cfg.from = old_from;
}
int main(void)
{
xce_init_xcecd_log("/tmp/test_controller_connector.log", 1024 * 1024, 2);
@ -1604,6 +1647,7 @@ int main(void)
RUN_TEST(test_build_cluster_config_no_peers_synthesizes_single_candidate);
RUN_TEST(test_jobcontrol_signal_for_queued_start_is_kept);
RUN_TEST(test_jobcontrol_signal_for_unknown_job_fails);
RUN_TEST(test_jobcontrol_signal_for_queued_remote_task_is_kept);
RUN_TEST(
test_build_cluster_config_single_entry_peers_matches_synthesized_shape);
RUN_TEST(test_build_cluster_config_multi_candidate_passthrough);