Deadlock under concurrent multithreaded use when DEBUG logging is enabled via setup_logging()
Los mantenedores suelen responder en 2 días
@bewithgaurav ya está trabajando en esto.
Desde el 10/7/2026.
Evaluación
Este issue todavía no se ha evaluado.
Descripción
Describe the bug
When driver logging is enabled via mssql_python.setup_logging(output="file") (DEBUG level) and multiple threads concurrently open connections and execute statements (for example a ThreadPoolExecutor with 4 workers), the process permanently deadlocks. It sits at 0% CPU — fully frozen, not merely slow.
The same code with setup_logging not called does not deadlock. It also does not deadlock with a single worker thread. The trigger is therefore the combination of DEBUG logging + concurrency (workers > 1).
Environment
- mssql-python version: 1.10.0
- Python version: 3.12.11
- Operating system: macOS (arm64)
- Authentication:
ActiveDirectoryDefault(Entra ID) against a Microsoft Fabric Warehouse. The deadlock is in the logging path and is very likely authentication-independent.
Observed thread stacks
Captured with Python's faulthandler. The dumps were identical across 7 dumps over roughly 7 minutes, which confirms a permanent deadlock rather than slowness.
Thread A (opening a connection):
File ".../mssql_python/connection.py", line 571 in setautocommit
File ".../mssql_python/connection.py", line 410 in __init__
File ".../mssql_python/db_connection.py", line 55 in connect
-> (calls into Python logging) ...
File ".../logging/handlers.py", line 75 in emit
File ".../logging/__init__.py", line 1144 in flush # blocked here
Thread B (executing a statement, a COPY INTO):
File ".../mssql_python/cursor.py", line 1545 in execute # blocked in native execute
Server-side check
While the client is frozen, the database server shows no query running for this session. This confirms the block is entirely client-side and is not waiting on the server.
Hypothesized mechanism
mssql-python emits DEBUG log records from within native code paths (for example setautocommit during connect, and cursor.execute) that hold the GIL / internal locks. Under concurrency this creates a lock-acquisition cycle with Python's logging Handler locks across threads:
- Thread A holds the logging handler lock and is blocked in
flush. - Thread B is blocked in native
executeand cannot proceed.
This is a classic logging-from-native-under-the-GIL deadlock. It only reproduces with workers > 1.
Steps to reproduce (minimal sketch)
- Call
mssql_python.setup_logging(output="file")to enable DEBUG logging. - From
N >= 2threads, concurrently open connections (autocommit=True) and run statements against the same server.
The process deadlocks within seconds to a couple of minutes.
Expected behavior
Enabling DEBUG logging should not affect correctness. Concurrent, multithreaded workloads should run to completion whether or not setup_logging is enabled.
Workaround
Do not enable setup_logging for concurrent / multithreaded workloads.
Impact
This makes the DEBUG logging feature unusable for any multithreaded application (for example parallel data-loading), which is precisely the scenario where enabling DEBUG logging is most valuable for diagnosis.
Possibly related issues
The following existing issues appear related but are distinct from this report:
- #540 — GIL held for the entire duration of
cursor.execute()(describes the native-call-holds-GIL behaviour that is part of the hypothesized mechanism here, but is about starvation rather than a permanent deadlock and does not involve logging). - #321 — multithreaded hang/deadlock with 3+ threads (does not involve logging; closed as non-reproducible).
- #421 — hang with
setup_loggingenabled (single-threaded, diagnosed as a driver-load hang on Linux rather than a concurrency logging-lock deadlock).
- Lenguaje dominante
- Python
- Estrellas
- 478
- Forks
- 62
- Merge medio
- 3 d 19 min
- PR fusionados (30 d)
- 28
Preparar el entorno
Inicia el contenedor de desarrollo del proyecto en tu navegador, con tu propia cuenta de GitHub.
- Sin Dockerfile ni archivo de Docker Compose
- Tiene una plantilla de pull request
- Leer la guía de contribución
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 microsoft/mssql-python
-
area: bulk-copy triage needed
Dificultad 2/5 1-3 horas Aptitud para principiantes 70/100
microsoft/mssql-python#843 · 1 comentario ·
Los mantenedores suelen responder en 2 días
-
triage needed
Dificultad 4/5 3-5 días Aptitud para principiantes 35/100
microsoft/mssql-python#846 · 1 comentario ·
Los mantenedores suelen responder en 2 días
-
macOS: encrypted connections fail after Homebrew moved the `openssl` alias to `openssl@4`Posiblemente ocupada @bewithgaurav la tomó hace 14 días. Abiertoarea: packaging-platform bug triage needed
Dificultad 4/5 3-5 días Aptitud para principiantes 55/100
microsoft/mssql-python#826 · 2 comentarios · 1 asignado ·
Los mantenedores suelen responder en 2 días
-
Announcement: mssql-python is coming to Django through mssql-django 2.0Quizá libre de nuevo @bewithgaurav la tomó hace 41 días y no hay ningún pull request abierto. Abiertoannouncement
microsoft/mssql-python#748 · 1 asignado ·
Los mantenedores suelen responder en 2 días
-
Connection pool can briefly exceed max_size when pooling is disabled under loadPosiblemente ocupada @bewithgaurav la tomó hace 23 días. Abiertoarea: connectivity-auth bug triage done under development
Dificultad 4/5 3-5 días Aptitud para principiantes 62/100
microsoft/mssql-python#746 · 1 comentario · 1 asignado ·
Los mantenedores suelen responder en 2 días
Todos los issues de microsoft/mssql-python
Issues similares
-
documentation pkg: sphinx-needs
Dificultad 1/5 Menos de una hora Aptitud para principiantes 82/100
useblocks/sphinx-needs#2255 ·
Los mantenedores suelen responder en 1 día
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 60/100
home-assistant/core#186538 ·
Los mantenedores suelen responder en 1 día
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 72/100
btclib-org/btclib-secp256k1#1181 ·
Los mantenedores suelen responder en 1 día
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 65/100
Los mantenedores suelen responder en 1 día
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 78/100
pyrite-wiki/pyrite#917 ·
Los mantenedores suelen responder en 1 día