From 1a182a98f76ce8c624bbaf3882e40d799e867338 Mon Sep 17 00:00:00 2001 From: Jens Hedegaard Nielsen Date: Wed, 29 Oct 2014 19:32:42 +0000 Subject: [PATCH 1/4] Use map_async and get to avoid a deadlock --- setupext.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/setupext.py b/setupext.py index 5479573b276d..3283f64763b0 100755 --- a/setupext.py +++ b/setupext.py @@ -1788,7 +1788,8 @@ def check_requirements(self): except: return "unknown (can not use multiprocessing to determine)" try: - success, msg = p.map(backend_gtk3agg_internal_check, [0])[0] + res = p.map_async(backend_gtk3agg_internal_check, [0]) + success, msg = res.get(timeout=5)[0] except: success = False msg = "Could not determine" @@ -1852,7 +1853,8 @@ def check_requirements(self): p = multiprocessing.Pool() except: return "unknown (can not use multiprocessing to determine)" - success, msg = p.map(backend_gtk3cairo_internal_check, [0])[0] + res = p.map_async(backend_gtk3cairo_internal_check, [0]) + success, msg = res.get(timeout=5)[0] p.close() p.join() if success: @@ -1988,7 +1990,8 @@ def check_requirements(self): else: # Multiprocessing OK try: - msg = p.map(self.callback, [self])[0] + res = p.map_async(self.callback, [self]) + msg = res.get(timeout=5)[0] except: # If we hit an error on multiprocessing raise it raise From fd9940f46d89e40c25742c0c91ee4e33ffda4478 Mon Sep 17 00:00:00 2001 From: Jens Hedegaard Nielsen Date: Wed, 29 Oct 2014 19:37:16 +0000 Subject: [PATCH 2/4] Wrap gtk3cairo test in try except --- setupext.py | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/setupext.py b/setupext.py index 3283f64763b0..4ff5f969f344 100755 --- a/setupext.py +++ b/setupext.py @@ -1853,10 +1853,15 @@ def check_requirements(self): p = multiprocessing.Pool() except: return "unknown (can not use multiprocessing to determine)" - res = p.map_async(backend_gtk3cairo_internal_check, [0]) - success, msg = res.get(timeout=5)[0] - p.close() - p.join() + try: + res = p.map_async(backend_gtk3cairo_internal_check, [0]) + success, msg = res.get(timeout=5)[0] + except: + success = False + raise + finally: + p.close() + p.join() if success: BackendAgg.force = True From ebee64b85e62d1c2518902dc3be641217af8b0ab Mon Sep 17 00:00:00 2001 From: Jens Hedegaard Nielsen Date: Wed, 29 Oct 2014 22:58:45 +0000 Subject: [PATCH 3/4] Forcefully terminate If process did not return within 5 sec assume that it is hanging and forcefully terminate --- setupext.py | 39 +++++++++++++++++++++++++++++++-------- 1 file changed, 31 insertions(+), 8 deletions(-) diff --git a/setupext.py b/setupext.py index 4ff5f969f344..e3d02db7c80a 100755 --- a/setupext.py +++ b/setupext.py @@ -1788,17 +1788,26 @@ def check_requirements(self): except: return "unknown (can not use multiprocessing to determine)" try: - res = p.map_async(backend_gtk3agg_internal_check, [0]) - success, msg = res.get(timeout=5)[0] + res = p.map_async(backend_gtk3agg_internal_check, [0]) + success, msg = res.get(timeout=5)[0] + except Queue.Empty: + p.terminate() + # No result returned. Probaly hanging, terminate the process. + success = False + raise except: + p.close() + # Some other error. success = False msg = "Could not determine" - finally: + raise + else: p.close() + finally: p.join() + if success: BackendAgg.force = True - return msg else: raise CheckFailed(msg) @@ -1856,15 +1865,22 @@ def check_requirements(self): try: res = p.map_async(backend_gtk3cairo_internal_check, [0]) success, msg = res.get(timeout=5)[0] + except Queue.Empty: + p.terminate() + # No result returned. Probaly hanging, terminate the process. + success = False + raise except: + p.close() success = False raise - finally: + else: p.close() + finally: p.join() + if success: BackendAgg.force = True - return msg else: raise CheckFailed(msg) @@ -1997,12 +2013,19 @@ def check_requirements(self): try: res = p.map_async(self.callback, [self]) msg = res.get(timeout=5)[0] + except Queue.Empty: + p.terminate() + # No result returned. Probaly hanging, terminate the process. + raise except: - # If we hit an error on multiprocessing raise it + # Some other error. + p.close() raise + else: + # Clean exit + p.close() finally: # Tidy up multiprocessing - p.close() p.join() return msg From cbddb9938520387144b730e8d8d26a125e9c17f4 Mon Sep 17 00:00:00 2001 From: Jens Hedegaard Nielsen Date: Thu, 30 Oct 2014 17:32:49 +0000 Subject: [PATCH 4/4] Catch the right error --- setupext.py | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/setupext.py b/setupext.py index e3d02db7c80a..32444984adee 100755 --- a/setupext.py +++ b/setupext.py @@ -13,7 +13,6 @@ import warnings from textwrap import fill - PY3 = (sys.version_info[0] >= 3) @@ -1789,12 +1788,12 @@ def check_requirements(self): return "unknown (can not use multiprocessing to determine)" try: res = p.map_async(backend_gtk3agg_internal_check, [0]) - success, msg = res.get(timeout=5)[0] - except Queue.Empty: + success, msg = res.get(timeout=10)[0] + except multiprocessing.TimeoutError: p.terminate() # No result returned. Probaly hanging, terminate the process. success = False - raise + raise CheckFailed("Check timed out") except: p.close() # Some other error. @@ -1864,12 +1863,12 @@ def check_requirements(self): return "unknown (can not use multiprocessing to determine)" try: res = p.map_async(backend_gtk3cairo_internal_check, [0]) - success, msg = res.get(timeout=5)[0] - except Queue.Empty: + success, msg = res.get(timeout=10)[0] + except multiprocessing.TimeoutError: p.terminate() # No result returned. Probaly hanging, terminate the process. success = False - raise + raise CheckFailed("Check timed out") except: p.close() success = False @@ -2012,11 +2011,11 @@ def check_requirements(self): # Multiprocessing OK try: res = p.map_async(self.callback, [self]) - msg = res.get(timeout=5)[0] - except Queue.Empty: + msg = res.get(timeout=10)[0] + except multiprocessing.TimeoutError: p.terminate() # No result returned. Probaly hanging, terminate the process. - raise + raise CheckFailed("Check timed out") except: # Some other error. p.close()