Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit a86d4fb

Browse filesBrowse files
committed
Cleanup and avoid refleaks OSX Timer__timer_start.
Reference leaks where occurring with early `return NULL`, e.g. if `PyObject_IsTrue(attribute)` or `PyMethod_Check(attribute)` failed. Also there's plenty of cases where one doesn't need to set the error message, as PyObject_GetAttrString (for example) will set the correct exception. Also apply similar cleanups to drawRect, even though it doesn't actually suffer from refleaks.
1 parent c292827 commit a86d4fb
Copy full SHA for a86d4fb

File tree

Expand file treeCollapse file tree

2 files changed

+27
-59
lines changed
Open diff view settings
Filter options
Expand file treeCollapse file tree

2 files changed

+27
-59
lines changed
Open diff view settings
Collapse file

‎lib/matplotlib/backends/backend_macosx.py‎

Copy file name to clipboardExpand all lines: lib/matplotlib/backends/backend_macosx.py
-2Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,10 +55,8 @@ def _set_device_scale(self, value):
5555

5656
def _draw(self):
5757
renderer = self.get_renderer(cleared=self.figure.stale)
58-
5958
if self.figure.stale:
6059
self.figure.draw(renderer)
61-
6260
return renderer
6361

6462
def draw(self):
Collapse file

‎src/_macosx.m‎

Copy file name to clipboardExpand all lines: src/_macosx.m
+27-57Lines changed: 27 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1672,26 +1672,15 @@ -(void)drawRect:(NSRect)rect
16721672
goto exit;
16731673
}
16741674
}
1675-
1676-
renderer = PyObject_CallMethod(canvas, "_draw", "", NULL);
1677-
if (!renderer)
1678-
{
1675+
if (!(renderer = PyObject_CallMethod(canvas, "_draw", "", NULL))
1676+
|| !(renderer_buffer = PyObject_GetAttrString(renderer, "_renderer"))) {
16791677
PyErr_Print();
16801678
goto exit;
16811679
}
1682-
1683-
renderer_buffer = PyObject_GetAttrString(renderer, "_renderer");
1684-
if (!renderer_buffer) {
1685-
PyErr_Print();
1686-
goto exit;
1687-
}
1688-
16891680
if (_copy_agg_buffer(cr, renderer_buffer)) {
16901681
printf("copy_agg_buffer failed\n");
16911682
goto exit;
16921683
}
1693-
1694-
16951684
if (!NSIsEmptyRect(rubberband)) {
16961685
NSFrameRect(rubberband);
16971686
}
@@ -2391,63 +2380,37 @@ static void context_cleanup(const void* info)
23912380
CFRunLoopRef runloop;
23922381
CFRunLoopTimerRef timer;
23932382
CFRunLoopTimerContext context;
2394-
double milliseconds;
23952383
CFAbsoluteTime firstFire;
23962384
CFTimeInterval interval;
2397-
PyObject* attribute;
2398-
PyObject* failure;
2385+
PyObject* py_interval = NULL, * py_single = NULL, * py_on_timer = NULL;
2386+
int single;
23992387
runloop = CFRunLoopGetCurrent();
24002388
if (!runloop) {
24012389
PyErr_SetString(PyExc_RuntimeError, "Failed to obtain run loop");
24022390
return NULL;
24032391
}
2404-
attribute = PyObject_GetAttrString((PyObject*)self, "_interval");
2405-
if (attribute==NULL)
2406-
{
2407-
PyErr_SetString(PyExc_AttributeError, "Timer has no attribute '_interval'");
2408-
return NULL;
2409-
}
2410-
milliseconds = PyFloat_AsDouble(attribute);
2411-
failure = PyErr_Occurred();
2412-
Py_DECREF(attribute);
2413-
if (failure) return NULL;
2414-
attribute = PyObject_GetAttrString((PyObject*)self, "_single");
2415-
if (attribute==NULL)
2416-
{
2417-
PyErr_SetString(PyExc_AttributeError, "Timer has no attribute '_single'");
2418-
return NULL;
2392+
if (!(py_interval = PyObject_GetAttrString((PyObject*)self, "_interval"))
2393+
|| ((interval = PyFloat_AsDouble(py_interval) / 1000.), PyErr_Occurred())
2394+
|| !(py_single = PyObject_GetAttrString((PyObject*)self, "_single"))
2395+
|| ((single = PyObject_IsTrue(py_single)) == -1)
2396+
|| !(py_on_timer = PyObject_GetAttrString((PyObject*)self, "_on_timer"))) {
2397+
goto exit;
24192398
}
2420-
// Need to tell when to first fire this timer, so get the current time
2421-
// and add an interval.
2422-
interval = milliseconds / 1000.0;
2399+
// (current time + interval) is time of first fire.
24232400
firstFire = CFAbsoluteTimeGetCurrent() + interval;
2424-
switch (PyObject_IsTrue(attribute)) {
2425-
case 1:
2426-
interval = 0;
2427-
break;
2428-
case 0: // Set by default above
2429-
break;
2430-
case -1:
2431-
default:
2432-
PyErr_SetString(PyExc_ValueError, "Cannot interpret _single attribute as True of False");
2433-
return NULL;
2434-
}
2435-
Py_DECREF(attribute);
2436-
attribute = PyObject_GetAttrString((PyObject*)self, "_on_timer");
2437-
if (attribute==NULL)
2438-
{
2439-
PyErr_SetString(PyExc_AttributeError, "Timer has no attribute '_on_timer'");
2440-
return NULL;
2401+
if (single) {
2402+
interval = 0;
24412403
}
2442-
if (!PyMethod_Check(attribute)) {
2404+
if (!PyMethod_Check(py_on_timer)) {
24432405
PyErr_SetString(PyExc_RuntimeError, "_on_timer should be a Python method");
2444-
return NULL;
2406+
goto exit;
24452407
}
2408+
Py_INCREF(py_on_timer);
24462409
context.version = 0;
24472410
context.retain = NULL;
24482411
context.release = context_cleanup;
24492412
context.copyDescription = NULL;
2450-
context.info = attribute;
2413+
context.info = py_on_timer;
24512414
timer = CFRunLoopTimerCreate(kCFAllocatorDefault,
24522415
firstFire,
24532416
interval,
@@ -2456,9 +2419,8 @@ static void context_cleanup(const void* info)
24562419
timer_callback,
24572420
&context);
24582421
if (!timer) {
2459-
Py_DECREF(attribute);
24602422
PyErr_SetString(PyExc_RuntimeError, "Failed to create timer");
2461-
return NULL;
2423+
goto exit;
24622424
}
24632425
if (self->timer) {
24642426
CFRunLoopTimerInvalidate(self->timer);
@@ -2469,7 +2431,15 @@ static void context_cleanup(const void* info)
24692431
* the timer lost before we have a chance to decrease the reference count
24702432
* of the attribute */
24712433
self->timer = timer;
2472-
Py_RETURN_NONE;
2434+
exit:
2435+
Py_XDECREF(py_interval);
2436+
Py_XDECREF(py_single);
2437+
Py_XDECREF(py_on_timer);
2438+
if (PyErr_Occurred()) {
2439+
return NULL;
2440+
} else {
2441+
Py_RETURN_NONE;
2442+
}
24732443
}
24742444

24752445
static PyObject*

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.