python / python/cpython

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

オープン
#148,428 コメント 1 件 リアクション 0 件 担当者 0 名 GitHub で見る

まだ誰も着手していません。

stdlib topic-XML type-bug
主要言語
Python
スター
77.2k
フォーク
35.9k
PR マージ指標
PR 指標を取得中

説明

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

コントリビューションガイド

コントリビューションガイドを開く

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

調査の方向性

まず DOMEventStream と pulldom.parse() から始め、次に test_pulldom.py を調べます。特に、36 行目付近にある既存のクリーンアップを確認してください。ResourceWarning を再現し、filename とユーザーが提供したストリームの所有権の挙動を検証します。ハンドルをリークさせずに、ライフサイクルのクリーンアップとコンテキストマネージャーの挙動がテストでカバーされていれば完了です。

索引モデルが issue の本文から書いたものです。

評価

技術スタック
python
領域
backend
issue の種類
バグ
難易度
3/5
見積もり時間
1〜2日
活発さ
停滞
明瞭さ
明確に書かれている
初心者へのやさしさ
35/100

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。