diff --git a/src/worker/src/inter_job_utils.c b/src/worker/src/inter_job_utils.c index bbeccd40..de78fa87 100644 --- a/src/worker/src/inter_job_utils.c +++ b/src/worker/src/inter_job_utils.c @@ -242,10 +242,13 @@ char* generate_url(port_info_t port, int interactive_mode) return NULL; } + /* url is a URL_MAX_LENGTH buffer -- sizing the snprintf with + * CMD_MAX_LENGTH here is a latent overflow that glibc's _FORTIFY_SOURCE + * build turns into a SIGABRT (__chk_fail) on the first interactive job. */ if (interactive_mode == TTY || interactive_mode == DISPLAY) { - snprintf(url, CMD_MAX_LENGTH, "http://%s:%d", local_ip, port.tty_port); + snprintf(url, URL_MAX_LENGTH, "http://%s:%d", local_ip, port.tty_port); } else if (interactive_mode == XJOB) { - snprintf(url, CMD_MAX_LENGTH, "%s::%d", local_ip, port.xjob_port); + snprintf(url, URL_MAX_LENGTH, "%s::%d", local_ip, port.xjob_port); } else { free(url); free(local_ip); diff --git a/src/worker/src/xcecd_worker.c b/src/worker/src/xcecd_worker.c index 217fd3f8..4abb2f2a 100644 --- a/src/worker/src/xcecd_worker.c +++ b/src/worker/src/xcecd_worker.c @@ -58,7 +58,7 @@ uv_loop_t* uv_loop = NULL; static void check_and_reconnect(); static void worker_reconnect_callback(bool connected); -static void xjob_start_vnc(); +static int xjob_start_vnc(); static void xjob_stop_vnc(); static bool check_process_status(pid_t target_pid, int expected_signal, int timeout_seconds); @@ -599,7 +599,7 @@ static void check_and_reconnect() reconnect_retry_limit = 5; } -static void xjob_start_vnc() +static int xjob_start_vnc() { char jobidStr[64]; fmt_jobid(jobidStr, sizeof(jobidStr), jobid); @@ -618,7 +618,7 @@ static void xjob_start_vnc() XCECD_WORKER_LOG( XCE_LOG_ERROR, "XCE_SERVER_DIR not set, cannot find VNC pre-exec command"); - exit(1); + return -1; } } else { snprintf(vnc_start_cmd, sizeof(vnc_start_cmd), "%s %d", XJOB_PRE_EXEC, @@ -630,14 +630,14 @@ static void xjob_start_vnc() XCECD_WORKER_LOG(XCE_LOG_ERROR, "Failed to start VNC server: %s", vnc_start_cmd); - exit(1); + return -1; } if (export_display_env(port_info.xjob_port) == -1) { XCECD_WORKER_LOG( XCE_LOG_ERROR, "Failed to export DISPLAY environment variable for VNC server"); - exit(1); + return -1; } else { XCECD_WORKER_LOG( XCE_LOG_DEBUG3, @@ -655,7 +655,7 @@ static void xjob_start_vnc() "Timeout waiting for VNC server to start on port " "%d after %d seconds", port_info.xjob_port, timeout_seconds); - exit(1); + return -1; } XCECD_WORKER_LOG( @@ -668,6 +668,7 @@ static void xjob_start_vnc() XCECD_WORKER_LOG(XCE_LOG_DEBUG3, "VNC server started for job %s", jobidStr); + return 0; } static void xjob_stop_vnc() @@ -689,18 +690,20 @@ static void xjob_stop_vnc() XCECD_WORKER_LOG( XCE_LOG_ERROR, "XCE_SERVER_DIR not set, cannot find VNC post-exec command"); - exit(1); + return; } } else { snprintf(vnc_stop_cmd, sizeof(vnc_stop_cmd), "%s %d", XJOB_POST_EXEC, port_info.xjob_port); } + /* Cleanup-only path: a failed stop must not kill the worker or clobber + * the job's exit code -- the VNC server will be reaped when its job's + * user session goes away or by the next startvnc on this port. */ if (uv_proc_post_exec(&uv_proc_manager, vnc_stop_cmd, NULL) != 0) { XCECD_WORKER_LOG(XCE_LOG_ERROR, "Failed to stop VNC server: %s", vnc_stop_cmd); - - exit(1); + return; } XCECD_WORKER_LOG(XCE_LOG_DEBUG3, "VNC server stopped for job %s", @@ -834,9 +837,34 @@ static void worker_job_callback(job_assignment_t* info) /* export XCE environment variables here */ apply_env_vars(&mydata.env_vars, jobid); - /* X server start here (blocked) */ + /* X server start here (blocked). Failure must not kill the worker + * process: report JOB_FAILED with a reason and exit the worker loop + * normally, so the master can reap this instance and start a fresh one + * for the next job (previously exit(1) here took down the whole + * per-job worker with no user-visible reason). */ if (XJOB == mydata.transfer_info->interactive_mode) { - xjob_start_vnc(); + if (xjob_start_vnc() != 0) { + XCECD_WORKER_LOG(XCE_LOG_ERROR, + "Failed to start VNC server for job %s", + jobidStr); + xjob_stop_vnc(); /* best-effort cleanup of a partial start */ + + check_and_reconnect(); + + job_runtime_info.job_pid = 0; + job_runtime_info.job_status = JOB_FAILED; + job_runtime_info.worker_status = WORKER_EXITED; + job_runtime_info.exit_code = 1; + + ipc_worker_send_status( + &job_runtime_info, + "Failed to start VNC server (check worker log)"); + worker_exit_flag = 1; + return_code = 1; + FREEUP(job_cmd); + ipc_worker_run(UV_RUN_NOWAIT); + return; + } } /* Queue pre-exec */