Skip to content

Commit 5cbe37f

Browse files
authored
Merge pull request #9662 from dopplershift/osx-timer-crash
Fix crash when restarting OSX single shot timer
2 parents 2fdef9e + 259a89b commit 5cbe37f

File tree

1 file changed

+36
-55
lines changed

1 file changed

+36
-55
lines changed

src/_macosx.m

+36-55
Original file line numberDiff line numberDiff line change
@@ -348,8 +348,7 @@ static CGFloat _get_device_scale(CGContextRef cr)
348348
[pool release];
349349
}
350350

351-
Py_INCREF(Py_None);
352-
return Py_None;
351+
Py_RETURN_NONE;
353352
}
354353

355354
static PyObject*
@@ -362,8 +361,7 @@ static CGFloat _get_device_scale(CGContextRef cr)
362361
return NULL;
363362
}
364363
[view setNeedsDisplay: YES];
365-
Py_INCREF(Py_None);
366-
return Py_None;
364+
Py_RETURN_NONE;
367365
}
368366

369367
static PyObject*
@@ -376,8 +374,7 @@ static CGFloat _get_device_scale(CGContextRef cr)
376374
return NULL;
377375
}
378376
[view displayIfNeeded];
379-
Py_INCREF(Py_None);
380-
return Py_None;
377+
Py_RETURN_NONE;
381378
}
382379

383380
static PyObject*
@@ -420,8 +417,7 @@ static CGFloat _get_device_scale(CGContextRef cr)
420417
}
421418

422419
[view setRubberband: rubberband];
423-
Py_INCREF(Py_None);
424-
return Py_None;
420+
Py_RETURN_NONE;
425421
}
426422

427423
static PyObject*
@@ -434,8 +430,7 @@ static CGFloat _get_device_scale(CGContextRef cr)
434430
return NULL;
435431
}
436432
[view removeRubberband];
437-
Py_INCREF(Py_None);
438-
return Py_None;
433+
Py_RETURN_NONE;
439434
}
440435

441436
static NSImage* _read_ppm_image(PyObject* obj)
@@ -546,8 +541,7 @@ static CGFloat _get_device_scale(CGContextRef cr)
546541
if (error==0) close(channel[1]);
547542
if (interrupted) raise(SIGINT);
548543

549-
Py_INCREF(Py_None);
550-
return Py_None;
544+
Py_RETURN_NONE;
551545
}
552546

553547
static PyObject*
@@ -563,8 +557,7 @@ static CGFloat _get_device_scale(CGContextRef cr)
563557
data1: 0
564558
data2: 0];
565559
[NSApp postEvent: event atStart: true];
566-
Py_INCREF(Py_None);
567-
return Py_None;
560+
Py_RETURN_NONE;
568561
}
569562

570563
static PyMethodDef FigureCanvas_methods[] = {
@@ -770,8 +763,7 @@ static CGFloat _get_device_scale(CGContextRef cr)
770763
[window orderFrontRegardless];
771764
[pool release];
772765
}
773-
Py_INCREF(Py_None);
774-
return Py_None;
766+
Py_RETURN_NONE;
775767
}
776768

777769
static PyObject*
@@ -785,8 +777,7 @@ static CGFloat _get_device_scale(CGContextRef cr)
785777
[pool release];
786778
self->window = NULL;
787779
}
788-
Py_INCREF(Py_None);
789-
return Py_None;
780+
Py_RETURN_NONE;
790781
}
791782

792783
static PyObject*
@@ -808,8 +799,7 @@ static CGFloat _get_device_scale(CGContextRef cr)
808799
[pool release];
809800
}
810801
PyMem_Free(title);
811-
Py_INCREF(Py_None);
812-
return Py_None;
802+
Py_RETURN_NONE;
813803
}
814804

815805
static PyObject*
@@ -830,8 +820,7 @@ static CGFloat _get_device_scale(CGContextRef cr)
830820
if (result) {
831821
return result;
832822
} else {
833-
Py_INCREF(Py_None);
834-
return Py_None;
823+
Py_RETURN_NONE;
835824
}
836825
}
837826

@@ -1280,8 +1269,7 @@ -(void)save_figure:(id)sender
12801269
[button setEnabled: YES];
12811270
}
12821271
[pool release];
1283-
Py_INCREF(Py_None);
1284-
return Py_None;
1272+
Py_RETURN_NONE;
12851273
}
12861274

12871275
static PyObject*
@@ -1783,8 +1771,7 @@ -(void)save_figure:(id)sender
17831771
[pool release];
17841772
}
17851773

1786-
Py_INCREF(Py_None);
1787-
return Py_None;
1774+
Py_RETURN_NONE;
17881775
}
17891776

17901777
static PyMethodDef NavigationToolbar2_methods[] = {
@@ -1888,8 +1875,7 @@ -(void)save_figure:(id)sender
18881875
free(buffer);
18891876
return string;
18901877
}
1891-
Py_INCREF(Py_None);
1892-
return Py_None;
1878+
Py_RETURN_NONE;
18931879
}
18941880

18951881
static PyObject*
@@ -1906,8 +1892,7 @@ -(void)save_figure:(id)sender
19061892
case 4: break;
19071893
default: return NULL;
19081894
}
1909-
Py_INCREF(Py_None);
1910-
return Py_None;
1895+
Py_RETURN_NONE;
19111896
}
19121897

19131898
@implementation WindowServerConnectionManager
@@ -2845,8 +2830,7 @@ - (int)index
28452830
Py_BEGIN_ALLOW_THREADS
28462831
[NSApp run];
28472832
Py_END_ALLOW_THREADS
2848-
Py_INCREF(Py_None);
2849-
return Py_None;
2833+
Py_RETURN_NONE;
28502834
}
28512835

28522836
typedef struct {
@@ -2883,10 +2867,19 @@ static void timer_callback(CFRunLoopTimerRef timer, void* info)
28832867
PyObject* method = info;
28842868
PyGILState_STATE gstate = PyGILState_Ensure();
28852869
PyObject* result = PyObject_CallFunction(method, NULL);
2886-
if (result==NULL) PyErr_Print();
2870+
if (result) {
2871+
Py_DECREF(result);
2872+
} else {
2873+
PyErr_Print();
2874+
}
28872875
PyGILState_Release(gstate);
28882876
}
28892877

2878+
static void context_cleanup(const void* info)
2879+
{
2880+
Py_DECREF((PyObject*)info);
2881+
}
2882+
28902883
static PyObject*
28912884
Timer__timer_start(Timer* self, PyObject* args)
28922885
{
@@ -2902,10 +2895,6 @@ static void timer_callback(CFRunLoopTimerRef timer, void* info)
29022895
PyErr_SetString(PyExc_RuntimeError, "Failed to obtain run loop");
29032896
return NULL;
29042897
}
2905-
context.version = 0;
2906-
context.retain = 0;
2907-
context.release = 0;
2908-
context.copyDescription = 0;
29092898
attribute = PyObject_GetAttrString((PyObject*)self, "_interval");
29102899
if (attribute==NULL)
29112900
{
@@ -2934,6 +2923,7 @@ static void timer_callback(CFRunLoopTimerRef timer, void* info)
29342923
PyErr_SetString(PyExc_ValueError, "Cannot interpret _single attribute as True of False");
29352924
return NULL;
29362925
}
2926+
Py_DECREF(attribute);
29372927
attribute = PyObject_GetAttrString((PyObject*)self, "_on_timer");
29382928
if (attribute==NULL)
29392929
{
@@ -2944,6 +2934,10 @@ static void timer_callback(CFRunLoopTimerRef timer, void* info)
29442934
PyErr_SetString(PyExc_RuntimeError, "_on_timer should be a Python method");
29452935
return NULL;
29462936
}
2937+
context.version = 0;
2938+
context.retain = NULL;
2939+
context.release = context_cleanup;
2940+
context.copyDescription = NULL;
29472941
context.info = attribute;
29482942
timer = CFRunLoopTimerCreate(kCFAllocatorDefault,
29492943
0,
@@ -2953,44 +2947,31 @@ static void timer_callback(CFRunLoopTimerRef timer, void* info)
29532947
timer_callback,
29542948
&context);
29552949
if (!timer) {
2950+
Py_DECREF(attribute);
29562951
PyErr_SetString(PyExc_RuntimeError, "Failed to create timer");
29572952
return NULL;
29582953
}
2959-
Py_INCREF(attribute);
29602954
if (self->timer) {
2961-
CFRunLoopTimerGetContext(self->timer, &context);
2962-
attribute = context.info;
2963-
Py_DECREF(attribute);
2964-
CFRunLoopRemoveTimer(runloop, self->timer, kCFRunLoopCommonModes);
2955+
CFRunLoopTimerInvalidate(self->timer);
29652956
CFRelease(self->timer);
29662957
}
29672958
CFRunLoopAddTimer(runloop, timer, kCFRunLoopCommonModes);
29682959
/* Don't release the timer here, since the run loop may be destroyed and
29692960
* the timer lost before we have a chance to decrease the reference count
29702961
* of the attribute */
29712962
self->timer = timer;
2972-
Py_INCREF(Py_None);
2973-
return Py_None;
2963+
Py_RETURN_NONE;
29742964
}
29752965

29762966
static PyObject*
29772967
Timer__timer_stop(Timer* self)
29782968
{
29792969
if (self->timer) {
2980-
PyObject* attribute;
2981-
CFRunLoopTimerContext context;
2982-
CFRunLoopTimerGetContext(self->timer, &context);
2983-
attribute = context.info;
2984-
Py_DECREF(attribute);
2985-
CFRunLoopRef runloop = CFRunLoopGetCurrent();
2986-
if (runloop) {
2987-
CFRunLoopRemoveTimer(runloop, self->timer, kCFRunLoopCommonModes);
2988-
}
2970+
CFRunLoopTimerInvalidate(self->timer);
29892971
CFRelease(self->timer);
29902972
self->timer = NULL;
29912973
}
2992-
Py_INCREF(Py_None);
2993-
return Py_None;
2974+
Py_RETURN_NONE;
29942975
}
29952976

29962977
static void

0 commit comments

Comments
 (0)