Skip to content

fix: skip post-job hook when executor fails to boot#276

Open
cchristous wants to merge 1 commit into
semaphoreci:masterfrom
cchristous:post-job-hook-nil-deref-executor-boot-failure
Open

fix: skip post-job hook when executor fails to boot#276
cchristous wants to merge 1 commit into
semaphoreci:masterfrom
cchristous:post-job-hook-nil-deref-executor-boot-failure

Conversation

@cchristous

Copy link
Copy Markdown

Problem

When a job's executor fails to boot, the agent process crashes with a nil-pointer SIGSEGV instead of failing the job cleanly.

Root cause

In Job.RunWithOptions, the executor is started via PrepareEnvironment(). When that fails, executorRunning is false, so the regular commands and epilogues are correctly skipped — but the post-job hook was called unconditionally afterward:

if executorRunning {
    result = job.RunRegularCommands(options)
    ...
    if !job.Stopped {
        job.handleEpilogues(result)
    }
}

// reached even when executorRunning == false
job.runPostJobHook(options)

runPostJobHook runs the hook inside the executor (Executor.RunCommandWithOptions), which for DockerComposeExecutor/ShellExecutor calls e.Shell.NewProcessWithOutput(...). e.Shell is only assigned once the executor boots successfully, so on a failed boot it is nil and the call dereferences a nil pointer — crashing the whole agent process.

Fix

Gate the post-job hook on executorRunning, matching how the epilogues directly above it are already handled. When the executor never booted, the hook is skipped and the job finishes cleanly as failed (with the existing Failed to prepare executor / Executor failed to boot up log lines).

Test

Adds Test__PostJobHookSkippedWhenExecutorFailsToPrepare: a stub executor whose Prepare() fails drives RunWithOptions with a post-job hook configured, and the test asserts the hook is never attempted (and the job still finishes). The test fails without the guard and passes with it. The existing Test__UsePostJobHook continues to cover the success path.

Running the post-job hook through an executor that never started
dereferences a nil shell (SIGSEGV), crashing the agent process. Gate
it on executorRunning, matching how epilogues are already handled.
@cchristous cchristous marked this pull request as ready for review July 8, 2026 16:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant