Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 472ebaa

Browse files
authored
Merge pull request #25097 from richardsheridan/24820-figurecanvastkagg-memory-leak
fix FigureCanvasTkAgg memory leak via weakrefs
2 parents baebe44 + c0df1bd commit 472ebaa

File tree

1 file changed

+22
-2
lines changed

1 file changed

+22
-2
lines changed

lib/matplotlib/backends/_backend_tk.py

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import uuid
2+
import weakref
23
from contextlib import contextmanager
34
import logging
45
import math
@@ -200,14 +201,33 @@ def __init__(self, figure=None, master=None):
200201
# event to the window containing the canvas instead.
201202
# See https://wiki.tcl-lang.org/3893 (mousewheel) for details
202203
root = self._tkcanvas.winfo_toplevel()
203-
root.bind("<MouseWheel>", self.scroll_event_windows, "+")
204+
205+
# Prevent long-lived references via tkinter callback structure GH-24820
206+
weakself = weakref.ref(self)
207+
weakroot = weakref.ref(root)
208+
209+
def scroll_event_windows(event):
210+
self = weakself()
211+
if self is None:
212+
root = weakroot()
213+
if root is not None:
214+
root.unbind("<MouseWheel>", scroll_event_windows_id)
215+
return
216+
return self.scroll_event_windows(event)
217+
scroll_event_windows_id = root.bind("<MouseWheel>", scroll_event_windows, "+")
204218

205219
# Can't get destroy events by binding to _tkcanvas. Therefore, bind
206220
# to the window and filter.
207221
def filter_destroy(event):
222+
self = weakself()
223+
if self is None:
224+
root = weakroot()
225+
if root is not None:
226+
root.unbind("<Destroy>", filter_destroy_id)
227+
return
208228
if event.widget is self._tkcanvas:
209229
CloseEvent("close_event", self)._process()
210-
root.bind("<Destroy>", filter_destroy, "+")
230+
filter_destroy_id = root.bind("<Destroy>", filter_destroy, "+")
211231

212232
self._tkcanvas.focus_set()
213233

0 commit comments

Comments
 (0)