Skip to content

Windows: daemon-spawned git fails with "exit status 0xc0000142" once the launching shell exits #73

@njt

Description

@njt

Symptom

On Windows, after a kata daemon has been running for a while, every command that reaches the daemon fails:

PS C:\src\some-repo> kata list
kata: git remote: exit status 0xc0000142

0xc0000142 is the Windows status code STATUS_DLL_INIT_FAILEDgit is failing to initialize as a process, not failing logically.

Root cause

git remote is run inside the daemon (internal/daemon/handlers_projects.goconfig.ComputeAliasIdentityreadGitRemoterunGit), to resolve a workspace's project identity. The kata: prefix is the CLI relaying the daemon's error.

The auto-started daemon is spawned by daemonclient.autoStart. On Windows detachChild is a no-op, so the daemon is created sharing the console of whatever shell first launched it. When that launching kata process exits and its console is torn down, the long-lived daemon is left holding a handle to a destroyed console. Git for Windows is built on the msys2 runtime, which requires a usable console to initialize; spawned against a dead console it aborts at startup with STATUS_DLL_INIT_FAILED (0xc0000142). Every subsequent daemon command that resolves identity then fails.

Reproduction

  1. Run any kata command that auto-starts a daemon (e.g. kata list).
  2. Close / exit the shell that launched it (its console is destroyed).
  3. From a new shell, run kata list again → git remote: exit status 0xc0000142.

Confirmed against a daemon that had been running for three days; kata daemon stop followed by a fresh kata list (daemon re-attached to a live console) works until that launcher exits again.

Fix

Detach the auto-started daemon properly so it never depends on the caller's console or stdio:

  • Create the daemon with DETACHED_PROCESS | CREATE_NEW_PROCESS_GROUP (the Windows analogue of the Unix Setpgid). With no inherited console, Windows allocates a fresh console for each git child and it initializes normally.
  • Route the auto-started daemon's stdout/stderr to a daemon.log file instead of inheriting the caller's stderr. A now-correctly-surviving daemon that holds the caller's stderr pipe hangs any parent that captures output (command substitution, CI, pipelines); this avoids that and persists daemon logs.

PR to follow.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions