Summary
In TUI mode on Linux with home directories on GPFS/NFS, the CLI hangs indefinitely at "Loading: N skills". The binary stops logging almost immediately after startup and never becomes responsive. The hang occurs even with no MCP servers configured.
Symptom
The log line gh CLI availability check completed never appears. MCP clients never start. The binary displays "Loading: N skills" forever.
Hanging run (GPFS, heavy concurrent I/O):
T+0s Starting Copilot CLI: 1.0.69
T+∞ Loading: 1 instruction, N skills ← stuck
[gh CLI check callback never fires, MCP clients never start]
Working run:
T+0.09s Registering foreground session
T+0.27s gh CLI availability check completed
T+1.04s Starting MCP clients...
T+5-20s AI response received ✓
Environment
- Linux (RHEL 8), home directory on GPFS or NFS
- Hangs intermittently without any MCP configuration; hangs more reliably when
command:-based MCP servers that exit immediately are configured (e.g. misconfigured MCPs that crash on startup)
- Not reproducible on macOS (Darwin uses kqueue for child-process events, not signalfd)
What is known
During startup, the binary spawns a which gh subprocess (via clone(SIGCHLD)) to check if the gh CLI is available. On GPFS systems with many concurrent I/O threads, the callback for this subprocess completion never fires. Without it, MCP clients never start and the TUI hangs.
strace -qq -e trace=none -f -o /dev/null wrapping the binary consistently and immediately fixes the hang. The -f flag (attach ptrace to all threads via PTRACE_O_TRACECLONE) is required — without it the hang persists. This strongly suggests the issue is related to how SIGCHLD is delivered across threads under heavy I/O load on Linux.
The suspected mechanism is a race in libuv's signalfd-based child-process tracking: SIGCHLD from the which gh subprocess is missed when all Tokio worker threads are busy with concurrent GPFS I/O. However, this has not been confirmed at the kernel level — the exact reason strace -f fixes it is inferred, not directly observed.
Having command:-based MCP servers that exit immediately (crashed/misconfigured MCPs) makes the hang more likely to occur, but is not required — the hang can occur with no MCP configuration at all under sufficient GPFS load.
Workaround
#!/bin/bash
# ~/bin/copilot wrapper
exec strace -qq -e trace=none -f -o /dev/null /path/to/copilot-linux-x64/copilot "$@"
Zero syscall-tracing overhead. The -f flag is required.
Suggested fix
- Add a timeout/fallback for the
gh CLI check — if the subprocess does not complete within ~500ms, assume gh is unavailable and continue startup. This would prevent the hang regardless of the signal delivery issue.
- Decouple MCP client startup from the
gh CLI check — MCP initialization should not be gated on an optional subprocess check. Starting MCP clients unconditionally would eliminate the hang.
- Investigate libuv signalfd behavior on Linux under high thread/I/O load — specifically whether SIGCHLD from short-lived subprocesses can be silently dropped when all threads are busy.
Option 1 or 2 would be the most impactful: a hung subprocess check should never be able to prevent the TUI from becoming usable.
Version
- Copilot CLI: 1.0.69
- OS: Linux (RHEL 8), home directory on GPFS
- Not reproducible on macOS
Summary
In TUI mode on Linux with home directories on GPFS/NFS, the CLI hangs indefinitely at "Loading: N skills". The binary stops logging almost immediately after startup and never becomes responsive. The hang occurs even with no MCP servers configured.
Symptom
The log line
gh CLI availability check completednever appears. MCP clients never start. The binary displays "Loading: N skills" forever.Environment
command:-based MCP servers that exit immediately are configured (e.g. misconfigured MCPs that crash on startup)What is known
During startup, the binary spawns a
which ghsubprocess (viaclone(SIGCHLD)) to check if theghCLI is available. On GPFS systems with many concurrent I/O threads, the callback for this subprocess completion never fires. Without it, MCP clients never start and the TUI hangs.strace -qq -e trace=none -f -o /dev/nullwrapping the binary consistently and immediately fixes the hang. The-fflag (attach ptrace to all threads viaPTRACE_O_TRACECLONE) is required — without it the hang persists. This strongly suggests the issue is related to how SIGCHLD is delivered across threads under heavy I/O load on Linux.The suspected mechanism is a race in libuv's
signalfd-based child-process tracking: SIGCHLD from thewhich ghsubprocess is missed when all Tokio worker threads are busy with concurrent GPFS I/O. However, this has not been confirmed at the kernel level — the exact reason strace -f fixes it is inferred, not directly observed.Having
command:-based MCP servers that exit immediately (crashed/misconfigured MCPs) makes the hang more likely to occur, but is not required — the hang can occur with no MCP configuration at all under sufficient GPFS load.Workaround
Zero syscall-tracing overhead. The
-fflag is required.Suggested fix
ghCLI check — if the subprocess does not complete within ~500ms, assumeghis unavailable and continue startup. This would prevent the hang regardless of the signal delivery issue.ghCLI check — MCP initialization should not be gated on an optional subprocess check. Starting MCP clients unconditionally would eliminate the hang.Option 1 or 2 would be the most impactful: a hung subprocess check should never be able to prevent the TUI from becoming usable.
Version