Skip to content

Node/libuv terminal detection clears the native runtime’s SIGCHLD handler, delaying  userPromptSubmitted  hooks until their full timeout #5007

Description

@aaroneng

Describe the bug

In GitHub Copilot CLI 1.0.88 on Linux, a  userPromptSubmitted  command hook can finish successfully in milliseconds, but Copilot does not recognize its completion until the configured timeout expires and the thread waiting for child process completion is woken up.

Starting copilot using "COPILOT_SETUP_TERMINAL=false copilot" avoid the issue.

We traced this to a process-wide SIGCHLD handler conflict between Copilot’s in-process native runtime and Node.js/libuv:

  1. The native runtime installs a SIGCHLD handler.
  2. Automatic terminal-setup detection invokes Node’s  child_process.exec  to run:
    ps -Ao pid=,ppid=,comm=
  3. libuv’s  uv_spawn  replaces the native runtime’s SIGCHLD handler.
  4. After that subprocess completes, libuv cleanup through  uv_signal_stop  resets SIGCHLD to  SIG_DFL , rather than restoring the native runtime’s handler.
  5. A subsequently launched prompt-hook process exits successfully, but its completion does not promptly wake the native runtime’s child waiter.
  6. Copilot collects the already-available exit status at our configured 300-second boundary for our hook processor and continues normally.

This is not a hook script taking five minutes to execute, nor a slow model response.

Environment

• GitHub Copilot CLI: 1.0.88
• Node.js version reported by CLI: v24.20.0
• Copilot runs on a remote Linux host.
• Two users connected to the same Linux host using the same remote account, through SSH:
• An SSH session from macOS consistently received fast responses with SSH sessions established using iTerm on the Mac.
• An SSH session from Windows reproduced the delay when using mobaxterm or putty.
• The configured  UserPromptSubmit  command hook had a 300-second timeout.
• The hook was loaded from the user-level hook configuration.

In the affected session:

• Copilot emits  hook.start  for  userPromptSubmitted .
• The hook process exits with status 0 in approximately 274 ms.
• SIGCHLD is delivered to the parent, but no corresponding signal handler runs.
• The child remains a zombie, parented to Copilot.
• Copilot remains active, but the prompt does not progress to a model request.
• Approximately 300 seconds after hook start (our set timeout), Copilot calls  wait4  again and collects the successful exit status.
• Copilot then emits  hook.end  with  success: true  and proceeds to the model.

Affected version

1.0.88

Steps to reproduce the behavior

  1. Configure a user-level  UserPromptSubmit  command hook with a 300-second timeout.
  2. Start interactive Copilot CLI 1.0.88 on Linux from the affected Windows-origin SSH session.
  3. Submit a simple text prompt that does not require a tool call.
  4. Observe  hook.start , but no timely  hook.end  or model response.
  5. Inspect the hook child: it has already exited and remains a zombie.
  6. Wait for the configured timeout boundary; Copilot recognizes the successful exit and responds.

Control tests:

• Removing the user-level hooks eliminated the prompt delay.
• With hooks enabled, the macOS-origin SSH session responded promptly.
• In the fast capture, the native runtime’s SIGCHLD handler remained effective and the hook child was reaped immediately.
• In the delayed capture, the terminal-detection  ps  subprocess ran and the parent’s SIGCHLD handler was subsequently reset to default.

Use this strace command to see the replacement of the SIGCHLD handler for

strace -ff -k -ttt -T
-e trace=%process,%signal
-e signal=all
-o /tmp/copilot-startup-stack-affected
copilot --log-level debug

Expected behavior

After a  userPromptSubmitted  hook process exits, Copilot should promptly collect its exit status, emit  hook.end , and proceed with the model turn.

Startup subprocesses launched through Node/libuv should not leave the native runtime’s child-exit notification mechanism disabled.

Additional context

No response

Activity

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

    area:platform-linuxLinux-specific: Wayland, X11, Ubuntu, Fedora, Alpine, ARM, terminal emulatorsarea:pluginsPlugin system, marketplace, hooks, skills, extensions, and custom agents

    Type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions