Hacktoberfest 2026: los issues que los mantenedores marcaron para octubre, abiertos y aptos para principiantes. Explorar issues de Hacktoberfest

CopilotClient.stop() leaks the CLI server's child process tree on Windows (orphaned node/copilot.exe per session)

Abierto
#1,804 2 comentarios 0 reacciones 0 asignados Ver en GitHub

Los mantenedores suelen responder en 1 día

Nadie ha tomado este issue todavía.

  • #1829 de @syf2211 — cerrado sin fusionar
  • #2073 de @rinceyuan — cerrado sin fusionar

Evaluación

Dificultad
4/5
Tiempo estimado
3-5 días
Aptitud para principiantes
52/100
Tipo de issue
Error
Claridad
Bastante claro
Estado de actividad
Tranquilo
Stack tecnológico
python

Línea de trabajo

Inspecciona client.py, especialmente CopilotClient.stop() y la creación de procesos de StdioRuntimeConnection; después, reproduce el bucle de Windows create_session()/stop() del issue mientras realizas el seguimiento de los procesos descendientes. Compara el comportamiento del ciclo de vida entre Windows y POSIX, y considera los enfoques indicados de Job Object o process-group. Se considera terminado cuando detener un cliente iniciado no deja procesos node.exe o copilot.exe descendientes huérfanos.

Escrito por el modelo de indexación a partir del texto del issue.

Descripción

bug
Summary

On Windows, CopilotClient.stop() does not terminate the CLI server's child process tree — only the top-level launcher process. Every create_session() / stop() cycle therefore orphans a full copilot process tree (node.exe + the copilot.exe broker/worker/webview helpers) that survives until its own idle timeout. In a long-running app that creates one client/session per unit of work (e.g. a batch/eval harness), this is a deterministic ~1 leaked process tree per session, which accumulates and eventually OOMs the host.

Environment
  • github-copilot-sdk (Python) 1.0.0b7 (also visible by inspection in current client.py)
  • Copilot CLI runtime 1.0.66-0
  • Windows 11, Python 3.11 (miniconda)
  • Transport: StdioRuntimeConnection, use_logged_in_user=True
Root cause

CopilotClient.stop() only calls terminate() / kill() on its own launcher Popen (self._process):

# client.py (stop)
if self._process and not self._is_external_server:
    self._process.terminate()
    try:
        self._process.wait(timeout=5)
    except subprocess.TimeoutExpired:
        self._process.kill()
    self._process = None

On Windows, terminating the launcher does not cascade to its descendants. The launcher (copilot.cmd → cmd.exe) spawns node.exe, which spawns the real copilot.exe server + helper processes; these are left orphaned and alive after stop().

Reproduction
import asyncio, psutil
from copilot import CopilotClient, StdioRuntimeConnection

CLI = r"C:\Users\<you>\AppData\Roaming\npm\copilot.cmd"

def n_copilot():
    return sum(p.info["name"] == "copilot.exe"
               for p in psutil.process_iter(["name"]))

async def main():
    for i in range(5):
        client = CopilotClient(
            connection=StdioRuntimeConnection(CLI, []),
            use_logged_in_user=True,
        )
        session = await client.create_session()
        await session.send("hello")
        # ...consume events until SessionIdle...
        await session.disconnect()
        await client.stop()
        print(f"iter {i}: copilot.exe alive = {n_copilot()}")

asyncio.run(main())

Observed (Windows): copilot.exe alive grows 1, 2, 3, 4, 5 — one orphaned tree per iteration, none reaped by stop().

Expected

After await client.stop() (for a client that spawned the server), the entire CLI server process tree should be terminated, leaving no orphaned node.exe / copilot.exe processes.

Workaround

Capture the launcher PID after create_session() and kill the whole tree explicitly on teardown — e.g. psutil.Process(pid).children(recursive=True) + kill all (enumerate before killing the parent), or taskkill /F /T /PID on Windows / os.killpg on POSIX.

Suggested fix

Have the SDK own the process-tree lifecycle so stop() reaps descendants:

  • Windows: assign the launcher to a Job Object with JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE, so the OS atomically kills the tree when the job/handle closes.
  • POSIX: spawn with start_new_session=True and os.killpg(os.getpgid(pid), SIGKILL) on stop.
  • Or a psutil-based recursive child kill inside stop().

This is likely related to the CLI-side reports of orphaned processes (e.g. github/copilot-cli#1368, #2279) but is reproducible purely through the SDK's own create_session()/stop() lifecycle.

Lenguaje dominante
TypeScript
Estrellas
10.5k
Forks
1.5k
Merge medio
1 d 11 h
PR fusionados (30 d)
81

Preparar el entorno

Abrir en Codespaces

Inicia el contenedor de desarrollo del proyecto en tu navegador, con tu propia cuenta de GitHub.

Primeros pasos

  1. Lee el issue completo y luego la guía de contribución del proyecto.
  2. Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
  3. Haz un fork del repositorio y trabaja en una rama.
  4. Abre un pull request que haga referencia al número del issue.

Más de github/copilot-sdk

Todos los issues de github/copilot-sdk

Issues similares

Más issues de TypeScript

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.