From 1eaa0840358b97319fe0f1e79498e8eadc3f13f0 Mon Sep 17 00:00:00 2001
From: Paul McCarthy <pauldmccarthy@gmail.com>
Date: Sun, 11 Jun 2017 16:07:16 +0100
Subject: [PATCH] The async module ensures that the idle timer is stopped on
 exit. If this isn't done, segfaults may sporadically occur.

---
 fsl/utils/async.py | 21 +++++++++++++++++----
 1 file changed, 17 insertions(+), 4 deletions(-)

diff --git a/fsl/utils/async.py b/fsl/utils/async.py
index a8e8efa0e..373e49e64 100644
--- a/fsl/utils/async.py
+++ b/fsl/utils/async.py
@@ -77,13 +77,11 @@ Other facilities
 The ``async`` module also defines the :func:`mutex` decorator, which is
 intended to be used to mark the methods of a class as being mutually exclusive.
 The ``mutex`` decorator uses the :class:`MutexFactory` class to do its work.
-
-
-.. todo:: You could possibly use ``props.callqueue`` to drive the idle loop.
 """
 
 
 import time
+import atexit
 import logging
 import functools
 import threading
@@ -213,6 +211,9 @@ def idleReset():
     global _idleTimer
     global _idleCallRate
 
+    if _idleTimer is not None:
+        _idleTimer.Stop()
+
     _idleRegistered = False
     _idleQueue      = queue.Queue()
     _idleQueueDict  = {}
@@ -220,6 +221,11 @@ def idleReset():
     _idleCallRate   = 200
 
 
+# Call idleReset on exit, in
+# case the idleTimer is active.
+atexit.register(idleReset)
+
+
 def getIdleTimeout():
     """Returns the current ``wx`` idle loop time out/call rate.
     """
@@ -306,7 +312,7 @@ def _wxIdleLoop(ev):
     if taskName is None: taskName = funcName
     else:                taskName = '{} [{}]'.format(taskName, funcName)
 
-    # Has enouggh time elapsed
+    # Has enough time elapsed
     # since the task was scheduled?
     # If not, re-queue the task.
     # If this is the only task on the
@@ -333,8 +339,15 @@ def _wxIdleLoop(ev):
             try:             _idleQueueDict.pop(task.name)
             except KeyError: pass
 
+    # More tasks on the queue?
+    # Request anotherd event
     if _idleQueue.qsize() > queueSizeOffset:
         ev.RequestMore()
+
+    # Otherwise use the idle
+    # timer to make sure that
+    # the loop keeps ticking
+    # over
     else:
         _idleTimer.Start(_idleCallRate, wx.TIMER_ONE_SHOT)
 
-- 
GitLab