text boxes never stop listening

オープン 初心者向け
#6,744 コメント 3 件 リアクション 0 件 担当者 0 名 GitHub で見る

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

  • #1 @CJstate による — マージされずにクローズ

評価

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

調査の方向性

まず _text_area.py と _input.py の、引用されている _on_mount メソッドを確認し、次に参考として _footer.py にある Footer のアンマウント時のクリーンアップを読みます。提供された再現コードを使い、シグナルを発行せずに、削除された Input と TextArea のウィジェットが保持されなくなったことを確認します。両方のウィジェットのメモリーリークが修正されたら完了です。

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

説明

The bug

TextArea._on_mount (_text_area.py:1904-1911) and Input._on_mount (_input.py:715-722) subscribe to self.screen.text_selection_started_signal with a callback that closes over self, and neither unsubscribes on unmount.
Signal keeps subscribers in a WeakKeyDictionary (signal.py:44), but the stored value is a wrapper holding that callback (signal.py:82-95), which holds self, so the weak key never dies. Dead subscribers are pruned only in publish() (signal.py:125-128), and nothing in Textual 8.2.8 publishes this signal. So every removed TextArea or Input stays alive, with its subtree, for the screen's lifetime.
Footer (_footer.py:333) and KeyPanel (_key_panel.py:182) already unsubscribe their own signal on unmount.

Example

import asyncio, gc
from textual.app import App
from textual.widgets import Input
async def main():
    app = App()
    async with app.run_test() as pilot:
        for _ in range(20):
            widget = Input()
            await app.mount(widget)
            await pilot.pause()
            await widget.remove()
            await pilot.pause()
        del widget
        gc.collect()
        print(sum(type(o) is Input for o in gc.get_objects()))  # 20, expected 0
asyncio.run(main())

One manual app.screen.text_selection_started_signal.publish(app.screen) drops it to 2. With TextArea in place of Input it stays at 20 until both a publish and an app theme change (the theme watcher is #6666).
Textual 8.2.8, Python 3.11.14, macOS.

Suggested fix

In TextArea and Input, unsubscribe on unmount, as Footer does:

self.screen.text_selection_started_signal.unsubscribe(self)
主要言語
Python
スター
37.6k
フォーク
1.4k
PR マージ指標
30日以内にマージされた PR はありません

環境構築

はじめの一歩

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

Textualize/textual のほかの issue

Textualize/textual の issue をすべて見る

似ている issue

Python の issue をもっと見る

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

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