Skip to content

gh-80937: Fix memory leak in tkinter createcommand#152294

Merged
serhiy-storchaka merged 1 commit into
python:mainfrom
serhiy-storchaka:tkinter-createcommand-leak
Jun 26, 2026
Merged

gh-80937: Fix memory leak in tkinter createcommand#152294
serhiy-storchaka merged 1 commit into
python:mainfrom
serhiy-storchaka:tkinter-createcommand-leak

Conversation

@serhiy-storchaka

Copy link
Copy Markdown
Member

A command created with createcommand() held a strong reference to the interpreter in its client data, forming an uncollectable reference cycle (interpreter -> Tcl command -> client data -> interpreter). The interpreter's refcount therefore never reached zero, so its commands were never deleted and their callbacks were never released, until the command was removed with deletecommand() or destroy().

The command now borrows the reference to the interpreter. It cannot outlive the interpreter, which deletes all of its commands (running their delete callbacks) when it is finalized.

A command created with createcommand() held a strong reference to the
interpreter, forming an uncollectable cycle (interpreter -> command ->
interpreter) that kept the interpreter and the callback alive until the
command was removed with deletecommand() or destroy().  The command now
borrows the reference; it cannot outlive the interpreter, which deletes its
commands when finalized.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@serhiy-storchaka serhiy-storchaka added needs backport to 3.13 bugs and security fixes needs backport to 3.14 bugs and security fixes needs backport to 3.15 pre-release feature fixes, bugs and security fixes labels Jun 26, 2026
@serhiy-storchaka serhiy-storchaka merged commit bbf7786 into python:main Jun 26, 2026
62 checks passed
@miss-islington-app

Copy link
Copy Markdown

Thanks @serhiy-storchaka for the PR 🌮🎉.. I'm working now to backport this PR to: 3.13, 3.14, 3.15.
🐍🍒⛏🤖

@bedevere-app

bedevere-app Bot commented Jun 26, 2026

Copy link
Copy Markdown

GH-152327 is a backport of this pull request to the 3.15 branch.

@bedevere-app bedevere-app Bot removed the needs backport to 3.15 pre-release feature fixes, bugs and security fixes label Jun 26, 2026
@bedevere-app

bedevere-app Bot commented Jun 26, 2026

Copy link
Copy Markdown

GH-152328 is a backport of this pull request to the 3.14 branch.

@bedevere-app bedevere-app Bot removed the needs backport to 3.14 bugs and security fixes label Jun 26, 2026
@bedevere-app

bedevere-app Bot commented Jun 26, 2026

Copy link
Copy Markdown

GH-152329 is a backport of this pull request to the 3.13 branch.

@bedevere-app bedevere-app Bot removed the needs backport to 3.13 bugs and security fixes label Jun 26, 2026
serhiy-storchaka added a commit that referenced this pull request Jun 26, 2026
…GH-152329)

A command created with createcommand() held a strong reference to the
interpreter, forming an uncollectable cycle (interpreter -> command ->
interpreter) that kept the interpreter and the callback alive until the
command was removed with deletecommand() or destroy().  The command now
borrows the reference; it cannot outlive the interpreter, which deletes its
commands when finalized.
(cherry picked from commit bbf7786)

Co-authored-by: Serhiy Storchaka <storchaka@gmail.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
serhiy-storchaka added a commit that referenced this pull request Jun 26, 2026
…GH-152328)

A command created with createcommand() held a strong reference to the
interpreter, forming an uncollectable cycle (interpreter -> command ->
interpreter) that kept the interpreter and the callback alive until the
command was removed with deletecommand() or destroy().  The command now
borrows the reference; it cannot outlive the interpreter, which deletes its
commands when finalized.
(cherry picked from commit bbf7786)

Co-authored-by: Serhiy Storchaka <storchaka@gmail.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
serhiy-storchaka added a commit that referenced this pull request Jun 26, 2026
…GH-152327)

A command created with createcommand() held a strong reference to the
interpreter, forming an uncollectable cycle (interpreter -> command ->
interpreter) that kept the interpreter and the callback alive until the
command was removed with deletecommand() or destroy().  The command now
borrows the reference; it cannot outlive the interpreter, which deletes its
commands when finalized.
(cherry picked from commit bbf7786)

Co-authored-by: Serhiy Storchaka <storchaka@gmail.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
@serhiy-storchaka serhiy-storchaka deleted the tkinter-createcommand-leak branch June 26, 2026 19:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant