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

Skip to content

Commit 558f111

Browse files
authored
Merge pull request #23059 from greglucas/macosx-manager-refcount
FIX: Decrease figure refcount on close of a macosx figure
2 parents 3133213 + fe6366d commit 558f111

File tree

2 files changed

+16
-15
lines changed

2 files changed

+16
-15
lines changed

lib/matplotlib/backends/backend_macosx.py

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ def __init__(self, figure):
3737
super().__init__(figure=figure)
3838
self._draw_pending = False
3939
self._is_drawing = False
40+
# Keep track of the timers that are alive
41+
self._timers = set()
4042

4143
def draw(self):
4244
"""Render the figure and update the macosx canvas."""
@@ -59,14 +61,16 @@ def draw_idle(self):
5961

6062
def _single_shot_timer(self, callback):
6163
"""Add a single shot timer with the given callback"""
62-
# We need to explicitly stop (called from delete) the timer after
64+
# We need to explicitly stop and remove the timer after
6365
# firing, otherwise segfaults will occur when trying to deallocate
6466
# the singleshot timers.
6567
def callback_func(callback, timer):
6668
callback()
67-
del timer
69+
self._timers.remove(timer)
70+
timer.stop()
6871
timer = self.new_timer(interval=0)
6972
timer.add_callback(callback_func, callback, timer)
73+
self._timers.add(timer)
7074
timer.start()
7175

7276
def _draw_idle(self):
@@ -150,6 +154,14 @@ def _close_button_pressed(self):
150154
Gcf.destroy(self)
151155
self.canvas.flush_events()
152156

157+
def destroy(self):
158+
# We need to clear any pending timers that never fired, otherwise
159+
# we get a memory leak from the timer callbacks holding a reference
160+
while self.canvas._timers:
161+
timer = self.canvas._timers.pop()
162+
timer.stop()
163+
super().destroy()
164+
153165
@classmethod
154166
def start_main_loop(cls):
155167
_macosx.show()

src/_macosx.m

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,6 @@ @interface Window : NSWindow
193193
- (Window*)initWithContentRect:(NSRect)rect styleMask:(unsigned int)mask backing:(NSBackingStoreType)bufferingType defer:(BOOL)deferCreation withManager: (PyObject*)theManager;
194194
- (NSRect)constrainFrameRect:(NSRect)rect toScreen:(NSScreen*)screen;
195195
- (BOOL)closeButtonPressed;
196-
- (void)dealloc;
197196
@end
198197

199198
@interface View : NSView <NSWindowDelegate>
@@ -1239,19 +1238,9 @@ - (void)close
12391238
/* This is needed for show(), which should exit from [NSApp run]
12401239
* after all windows are closed.
12411240
*/
1242-
}
1243-
1244-
- (void)dealloc
1245-
{
1246-
PyGILState_STATE gstate;
1247-
gstate = PyGILState_Ensure();
1241+
// For each new window, we have incremented the manager reference, so
1242+
// we need to bring that down during close and not just dealloc.
12481243
Py_DECREF(manager);
1249-
PyGILState_Release(gstate);
1250-
/* The reference count of the view that was added as a subview to the
1251-
* content view of this window was increased during the call to addSubview,
1252-
* and is decreased during the call to [super dealloc].
1253-
*/
1254-
[super dealloc];
12551244
}
12561245
@end
12571246

0 commit comments

Comments
 (0)