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

Logging capture crashes when another thread registers a logger

Abierto Apto para principiantes
#15,237 0 comentarios 0 reacciones 0 asignados Ver en GitHub

Los mantenedores suelen responder en 1 día

@Spikhalskiy ya está trabajando en esto.

Desde el 21/10/2026.

  • #15238 de @Spikhalskiy — abierto

Evaluación

Dificultad
2/5
Tiempo estimado
1-3 horas
Aptitud para principiantes
78/100
Tipo de issue
Error
Claridad
Bien especificado
Estado de actividad
Activo
Stack tecnológico
python
Área
backend, testing

Línea de trabajo

El traceback apunta a _pytest/logging.py en catching_logs.__enter__, donde se itera sobre loggerDict.values(). Lee ese código de configuración y las pruebas relacionadas con la captura de logs; después, reproduce el caso de registro concurrente del issue. El trabajo estará terminado cuando la configuración de la captura ya no lance una excepción durante el registro concurrente de loggers y una prueba cubra la regresión.

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

Descripción

  • a detailed description of the bug or problem you are having
  • output of pip list from the virtual environment you are using
  • pytest and operating system versions
  • minimal example if possible

Description

catching_logs.__enter__ can raise RuntimeError: dictionary changed size during iteration when another thread calls logging.getLogger() during capture setup.

The regression was introduced by #14375 / 7e6161c68579eb58ecceaf8c6b6f6b1b2f46c28a, which iterates the live logging.root.manager.loggerDict.values() view. logging.getLogger() mutates that dictionary while holding logging's registry lock, but pytest's iteration does not use the lock or take a snapshot.

Reproduction

import logging
import threading

from _pytest.logging import catching_logs

mutation_completed = threading.Event()
worker = None

class TriggerLogger(logging.Logger):
    @property
    def propagate(self):
        global worker

        def register_logger():
            logging.getLogger("repro.concurrent-registration")
            mutation_completed.set()

        worker = threading.Thread(target=register_logger)
        worker.start()
        assert mutation_completed.wait(timeout=1)
        return True

    @propagate.setter
    def propagate(self, value):
        pass

manager = logging.root.manager
manager.loggerDict["repro.trigger"] = TriggerLogger("repro.trigger")

try:
    with catching_logs(logging.NullHandler()):
        pass
finally:
    if worker is not None:
        worker.join(timeout=1)

The property access happens after pytest's live dictionary iterator has yielded its first logger. The worker then uses the public logging.getLogger() API to mutate the registry before pytest requests the iterator's next value.

Actual result

File ".../_pytest/logging.py", line 366, in __enter__
    for logger in root_logger.manager.loggerDict.values():
RuntimeError: dictionary changed size during iteration

Expected result

Concurrent logger registration should not make capture setup fail.

Suggested fix

Snapshot the registry before inspecting the loggers:

for logger in list(root_logger.manager.loggerDict.values()):

This also matches the behavior described in #14375: loggers created after capture setup starts do not need to be discovered by that capture scope.

Environment

  • macOS 26.5.2 (Apple silicon)
  • Python 3.13.13
  • pytest 9.2.0.dev393+gc9bf1edf9 (main at c9bf1edf9e0d388f3e7bebc88576e608ffbc40a4)
  • Also reproduced with pytest 9.1.1 on Python 3.12
pip list
Package            Version
------------------ ----------------------------
argcomplete        3.6.3
attrs              25.4.0
certifi            2026.1.4
charset-normalizer 3.4.4
coverage           7.13.1
elementpath        5.1.0
execnet            2.1.2
hypothesis         6.150.0
idna               3.11
iniconfig          2.3.0
mock               5.2.0
numpy              2.4.1
packaging          25.0
pexpect             4.9.0
pluggy             1.6.0
ptyprocess         0.7.0
Pygments           2.19.2
pytest             9.2.0.dev393+gc9bf1edf9
pytest-xdist       3.8.0
PyYAML             6.0.3
requests           2.32.5
setuptools         80.9.0
sortedcontainers   2.4.0
urllib3            2.6.3
xmlschema          4.3.0
Lenguaje dominante
Python
Estrellas
14.6k
Forks
3.5k
Merge medio
3 d 2 h
PR fusionados (30 d)
35

Preparar el entorno

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 pytest-dev/pytest

Todos los issues de pytest-dev/pytest

Issues similares

Más issues de Python

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.