logging: `SMTPHandler.emit()` leaks the SMTP connection when sending fails
Nadie ha tomado este issue todavía.
- Lenguaje dominante
- Python
- Estrellas
- 77.2k
- Forks
- 35.9k
- Métricas de merge de PR
- Métricas de PR pendientes
Descripción
Bug report
Bug description:
SMTPHandler.emit() only closes its SMTP connection on the success path: smtp.quit() is the last statement of the try block (Lib/logging/handlers.py#L1109-L1154).
If starttls(), login() or send_message() raises, control jumps to except Exception: self.handleError(record) and the connection is never closed — cleanup is left to the garbage collector.
Reproducer
import gc, logging, logging.handlers, socket, threading, time
logging.raiseExceptions = False
open_conns = []
def handle(conn):
conn.sendall(b"220 fake ESMTP\r\n")
for line in conn.makefile("rb"):
cmd = line.strip().upper()
if cmd.startswith(b"EHLO"):
conn.sendall(b"250-fake\r\n250 AUTH PLAIN LOGIN\r\n")
elif cmd.startswith(b"AUTH"):
conn.sendall(b"535 authentication failed\r\n")
else:
conn.sendall(b"250 ok\r\n")
open_conns.remove(conn) # reached when the client closes the connection
conn.close()
def serve(listener):
while True:
conn, _ = listener.accept()
open_conns.append(conn)
threading.Thread(target=handle, args=(conn,), daemon=True).start()
listener = socket.create_server(("127.0.0.1", 0))
threading.Thread(target=serve, args=(listener,), daemon=True).start()
h = logging.handlers.SMTPHandler(("127.0.0.1", listener.getsockname()[1]),
"me@example.com", "you@example.com", "subject",
credentials=("user", "wrong-password"))
for i in range(5):
h.emit(logging.makeLogRecord({"msg": "hello"})) # SMTPAuthenticationError
time.sleep(0.5)
print("open connections after 5 failed emits:", len(open_conns))
gc.collect(); time.sleep(0.5)
print("after gc.collect():", len(open_conns))
Output on main:
open connections after 5 failed emits: 5
after gc.collect(): 0
CPython versions tested on:
CPython main branch
Operating systems tested on:
macOS
Linked PRs
- gh-155950
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.
Línea de trabajo
Comienza en Lib/logging/handlers.py, en SMTPHandler.emit(), y ejecuta el reproductor proporcionado del fallo de autenticación. Se considera terminado cuando los recorridos en los que fallan starttls(), login() o send_message() ya no dejan abiertas las conexiones SMTP; comprueba el comportamiento con el reproductor. La PR vinculada gh-155950 indica que el trabajo ya está en curso.
Escrito por el modelo de indexación a partir del texto del issue.
Evaluación
- Stack tecnológico
- python
- Área
- backend
- Tipo de issue
- Error
- Dificultad
- 2/5
- Tiempo estimado
- 1-3 horas
- Estado de actividad
- Estancado
- Claridad
- Bien especificado
- Aptitud para principiantes
- 25/100