patch = subprocess: SIGINT-killed child exits 1 instead of -2 on Python 3.13 (regression in 7.17.1)
Los mantenedores suelen responder en 1 día
Nadie ha tomado este issue todavía.
Evaluación
- Dificultad
- 3/5
- Tiempo estimado
- 1-2 días
- Aptitud para principiantes
- 68/100
- Tipo de issue
- Error
- Claridad
- Bien especificado
- Estado de actividad
- Activo
- Stack tecnológico
- python
- Área
- backend, testing-qa
Línea de trabajo
Start by reading the subprocess patch implementation and its tests, then reproduce the reported return-code difference with the supplied parent script on Python 3.13 and coverage 7.17.2. Compare behavior with 7.17.0 and without the patch to narrow the regression. Done means the patched child exits with return code -2 on SIGINT while the existing subprocess tests continue to pass.
Escrito por el modelo de indexación a partir del texto del issue.
Descripción
Describe the bug
With [run] patch = subprocess, a Python child process that is interrupted by SIGINT exits with return code 1 instead of dying from the signal (return code -2, as seen by subprocess). This started in 7.17.1 and is still there in 7.17.2. It only happens on Python 3.13; 3.12 and 3.14 are fine. Without patch = subprocess the child exits correctly.
The child still prints the usual KeyboardInterrupt traceback, so the interrupt is raised. Only the process exit status changes. Python normally re-raises an unhandled KeyboardInterrupt as a real SIGINT death at shutdown, and that seems to be skipped in the patched child.
This breaks callers that map a signal death to exit code 130. We pinned 7.17.0 in the meantime.
To Reproduce
.coveragerc:
[run]
patch = subprocess
parent.py:
import os, signal, subprocess, sys, time
child = subprocess.Popen(
[sys.executable, "-c", "import time; open('ready', 'w').close(); time.sleep(60)"]
)
while not os.path.exists("ready"):
time.sleep(0.05)
child.send_signal(signal.SIGINT)
print("child returncode:", child.wait())
os.remove("ready")
Commands, in an empty directory holding the two files above:
python3.13 -m venv venv
venv/bin/pip install coverage==7.17.2
venv/bin/coverage run parent.py
- Python: CPython 3.13.14 (3.12.13 and 3.14.6 are not affected)
- coverage.py: 7.17.1 and 7.17.2; 7.17.0 is fine
- Installed packages: only coverage
- Code: the two files above; no repo needed
- Commands: above
Expected: child returncode: -2
Actual on Python 3.13 with coverage 7.17.1 or 7.17.2: child returncode: 1
Results (Linux x86_64, CPython from python-build-standalone via uv), deterministic over repeated runs:
| Python | 7.17.0 | 7.17.1 | 7.17.2 | 7.17.2 without patch = subprocess |
|---|---|---|---|---|
| 3.12.13 | -2 | -2 | -2 | -2 |
| 3.13.14 | -2 | 1 | 1 | -2 |
| 3.14.6 | -2 | -2 | -2 | -2 |
A child that signals itself (os.kill(os.getpid(), signal.SIGINT) at module level) reproduced it only intermittently. An external SIGINT delivered while the child is blocked in time.sleep fails every time.
Expected behavior
The measured child's exit status is the same as without coverage: death by SIGINT (return code -2).
Additional context
- Linux 7.0 x86_64, glibc 2.43
- Same result with
COVERAGE_COREunset,ctrace,sysmonandpytrace
- Lenguaje dominante
- Python
- Estrellas
- 3.4k
- Forks
- 554
- Merge medio
- 1 d 10 h
- PR fusionados (30 d)
- 13
Preparar el entorno
Este proyecto no incluye contenedor de desarrollo, Dockerfile ni guía de contribución, así que la configuración corre por tu cuenta: empieza por su README y consulta nuestra guía para la primera contribución para los pasos generales.
Primeros pasos
- Lee el issue completo y luego la guía de contribución del proyecto.
- Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
- Haz un fork del repositorio y trabaja en una rama.
- Abre un pull request que haga referencia al número del issue.
Más de coveragepy/coveragepy
-
combine() crashes with DataError (SQLITE_CANTOPEN) when a parallel data file vanishes mid-combine (regression in 7.17.1)Posiblemente ocupada @Jinyong-Li la tomó hace 1 día. Abiertobug
Dificultad 2/5 1-3 horas Aptitud para principiantes 76/100
coveragepy/coveragepy#2364 ·
Los mantenedores suelen responder en 1 día
-
bug
Dificultad 2/5 1-3 horas Aptitud para principiantes 70/100
coveragepy/coveragepy#2182 · 4 comentarios ·
Los mantenedores suelen responder en 1 día
-
Dificultad 5/5 Más de una semana Aptitud para principiantes 35/100
coveragepy/coveragepy#2358 · 1 comentario ·
Los mantenedores suelen responder en 1 día
-
Deadlock in `switch_context()` when the GC runs measured code while `_clear_data` holds `data_lock`Abierto
Dificultad 4/5 3-5 días Aptitud para principiantes 48/100
coveragepy/coveragepy#2348 ·
Los mantenedores suelen responder en 1 día
-
patch = fork on its own stops measuring forked child processesPosiblemente ocupada @SwastikTripathi la tomó hace 17 días. Abierto
Dificultad 3/5 1-2 días Aptitud para principiantes 35/100
coveragepy/coveragepy#2340 ·
Los mantenedores suelen responder en 1 día
Todos los issues de coveragepy/coveragepy
Issues similares
-
bug
Dificultad 2/5 1-3 horas Aptitud para principiantes 74/100
igormcsouza/tether#278 ·
Los mantenedores suelen responder en 1 día
-
Dificultad 1/5 Menos de una hora Aptitud para principiantes 91/100
aws-samples/sample-per-model-bedrock#803 ·
Los mantenedores suelen responder en 1 día
-
documentation p1
Dificultad 2/5 1-3 horas Aptitud para principiantes 75/100
Los mantenedores suelen responder en 1 día
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 78/100
huggingface/accelerate#4511 ·
Los mantenedores suelen responder en 1 día
-
follow-up
Dificultad 2/5 1-3 horas Aptitud para principiantes 78/100
Los mantenedores suelen responder en 1 día