python / python/cpython

xml.dom.pulldom.DOMEventStream leaks file handles opened by parse()

Offen
#148,428 1 Kommentar 0 Reaktionen 0 zugewiesene Personen Auf GitHub ansehen

Dieses Issue hat noch niemand übernommen.

stdlib topic-XML type-bug
Vorherrschende Sprache
Python
Sterne
77.2k
Forks
35.9k
PR-Merge-Kennzahlen
PR-Kennzahlen ausstehend

Beschreibung

pulldom.parse() opens a file when called with a filename string, but the resulting DOMEventStream never closes it. The class has no close() method, no context manager support, and clear() just sets self.stream = None without closing.

This produces ResourceWarning: unclosed file and can lead to file descriptor exhaustion in long-running processes.

The documentation example at https://docs.python.org/3/library/xml.dom.pulldom.html#module-xml.dom.pulldom shows:

doc = pulldom.parse('sales_items.xml')
for event, node in doc:
    ...

— with no cleanup, so users following the docs will hit this.

Reproduction
import warnings, tempfile, os, gc
from xml.dom import pulldom

warnings.simplefilter('always', ResourceWarning)

fd, path = tempfile.mkstemp(suffix='.xml')
os.write(fd, b'<root><item>test</item></root>')
os.close(fd)

events = pulldom.parse(path)
for event, node in events:
    pass

# stream is still open after full iteration
print(f'stream.closed: {events.stream.closed}')  # False

# clear() doesn't close it either
events.clear()

del events
gc.collect()  # ResourceWarning: unclosed file ...

os.unlink(path)

The existing test in test_pulldom.py already works around this with self.addCleanup(handler.stream.close) (line 36), which further confirms the leak.

Suggested fix

Track whether parse() opened the file (vs. receiving a user-provided stream), then add close(), __enter__/__exit__, and __del__ with ResourceWarning to DOMEventStream. Update clear() to close owned streams.

This follows the same approach used for ElementTree.iterparse() (gh-140601).

Linked PRs
  • gh-148437

Beitragsleitfaden

Beitragsleitfaden öffnen

Erste Schritte

  1. Lies das ganze Issue und danach den Beitragsleitfaden des Projekts.
  2. Schreib ins Issue, dass du es übernimmst — das erspart doppelte Arbeit.
  3. Forke das Repository und arbeite in einem Branch.
  4. Öffne einen Pull Request, der die Issue-Nummer nennt.

Rechercherichtung

Beginne mit DOMEventStream und pulldom.parse() und untersuche anschließend test_pulldom.py, insbesondere die bestehende Bereinigung um Zeile 36. Reproduziere die ResourceWarning und überprüfe das Ownership-Verhalten für filename und vom Benutzer bereitgestellte Streams. Erledigt ist die Aufgabe, wenn die Bereinigung des Lebenszyklus und das Verhalten des Context-Managers durch Tests abgedeckt sind, ohne Handles zu leaken.

Vom Indexierungsmodell aus dem Issue-Text verfasst.

Bewertung

Tech-Stack
python
Bereich
backend
Issue-Typ
Bug
Schwierigkeit
3/5
Geschätzter Aufwand
1-2 Tage
Aktivitätsstatus
Veraltet
Klarheit
Klar beschrieben
Anfängerfreundlichkeit
35/100

Neue Issues direkt in Ihr Postfach

Eine kurze Übersicht über anfängerfreundliche GitHub-Issues.