Skip to content

No timeout on the cached git exec, unlike every other CLI call site (2.2.22) #557

Closed

Description

@herman925

Summary

In 2.2.22, the cached git command runner calls execFileSync("git", …) without a timeout, while every other external CLI call in the same bundle passes timeout: CLI_TIMEOUT (5000 ms). A git invocation that blocks therefore hangs the statusline process indefinitely, with nothing to reap it.

This is a separate hang path from the stdin issue in #485 / #420, which #421 addresses. Fixing the stdin read will not close this one.

Evidence

From the installed dist/ccstatusline.js (2.2.22), all 12 synchronous exec call sites, extracted with brace matching:

With timeout: CLI_TIMEOUT (6):

execFileSync("git",  args, { …, cwd, timeout: CLI_TIMEOUT, windowsHide: true })
execFileSync("ssh",  ["-G", host], { …, timeout: CLI_TIMEOUT, … })
execFileSync(cli,    ["--version"], { …, timeout: CLI_TIMEOUT, … })
execFileSync(cli,    ["auth", "status", "--hostname", host], { …, timeout: CLI_TIMEOUT, … })
execFileSync("gh",   args, { …, cwd, timeout: CLI_TIMEOUT, … })
execFileSync("glab", args, { …, cwd, timeout: CLI_TIMEOUT, … })

Without (6):

execFileSync("git", args, {          <-- the cached git runner
  encoding: "utf8",
  stdio: ["pipe", "pipe", "ignore"],
  env: { ...process.env, GIT_OPTIONAL_LOCKS: "0" },
  windowsHide: true,
  ...cwd2 ? { cwd: cwd2 } : {}
})
execSync("tput cols 2>/dev/null", { … })
execSync(`ps -o ppid= -p ${pid}`,  { …, shell: "/bin/sh" })
execSync(`ps -o tty=  -p ${pid}`,  { …, shell: "/bin/sh" })
execSync(`${cmd} 2>/dev/null | awk '{print $2}'`, { …, shell: "/bin/sh" })
spawnSync(command, args, { stdio: "ignore", windowsHide: true })

CLI_TIMEOUT = 5000.

The last five are local, fast, and mostly POSIX-only. The first is the interesting one: it sits immediately after the memory/persistent cache lookup in the git command helper, so it is the path every git widget takes on a cache miss.

Why it bites

On this machine the working repository lives on a Google Drive mount, where git is routinely slow and occasionally blocks. With the default gitCacheTtlSeconds: 5 and a refreshInterval of 10, the cache expires before every render, so this call runs on essentially every redraw. Multiply by several concurrent Claude Code sessions and any non-trivial hang rate accumulates.

Observed on this machine: 60 orphaned ccstatusline node processes, 4,511 MB resident, oldest 143.7 hours, every one with a dead parent. That population is presumably a mix of this path and the stdin path in #485 — I cannot attribute individual processes to one or the other after the fact, and I want to be careful not to claim more than I measured.

Suggested fix

Add timeout: CLI_TIMEOUT to the cached git runner, matching its sibling. One line, and it bounds the worst case to 5 s rather than forever.

Separately, and lower priority: when a sync exec does time out, Node throws but leaves nothing to clean up — there is no .kill( anywhere in the bundle except process.kill(process.pid, sig) inside the vendored signal-exit, which re-raises a signal on the current process rather than terminating a child. Worth a look if timed-out children are observed surviving.

Related

Those three concern the stdin read. This issue is about the exec path and is independent of them.

Environment

  • ccstatusline 2.2.22 (global npm install)
  • Windows 11, Claude Code, several concurrent sessions
  • Repository on a Google Drive (G:) mount

Activity

  1. added a commit that references this issue on Sep 10, 2026
    88c8717
  2. added a commit that references this issue on Sep 17, 2026
    273d997
  3. added a commit that references this issue on Oct 20, 2026
    8cfa244
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions