logging: `SMTPHandler.emit()` leaks the SMTP connection when sending fails
Nessuno ha ancora preso questa issue.
- Lingua principale
- Python
- Stelle
- 77.2k
- Fork
- 35.9k
- Metriche di merge delle PR
- Metriche PR in attesa
Descrizione
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
Guida per i contributori
Apri la guida per i contributori
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Direzione di ricerca
Inizia da Lib/logging/handlers.py, in SMTPHandler.emit(), ed esegui il riproduttore fornito per il fallimento dell'autenticazione. Il lavoro è completato quando i percorsi in cui falliscono starttls(), login() o send_message() non lasciano più aperte le connessioni SMTP; verifica il comportamento con il riproduttore. La PR collegata gh-155950 indica che il lavoro è già in corso.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Valutazione
- Stack tecnologico
- python
- Ambito
- backend
- Tipo di issue
- Bug
- Difficoltà
- 2/5
- Tempo stimato
- 1-3 ore
- Stato di attività
- Ferma
- Chiarezza
- Specificata chiaramente
- Idoneità per principianti
- 25/100