From 563083cf866fb3473ac10364658c82a6925844e6 Mon Sep 17 00:00:00 2001 From: Kenneth Lyons Date: Sun, 23 Jun 2019 12:14:52 -0700 Subject: [PATCH 1/2] Handle invalid file descriptor in exit --- pyqtgraph/__init__.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/pyqtgraph/__init__.py b/pyqtgraph/__init__.py index 2db79985..b1aa98aa 100644 --- a/pyqtgraph/__init__.py +++ b/pyqtgraph/__init__.py @@ -369,8 +369,12 @@ def exit(): ## close file handles if sys.platform == 'darwin': for fd in range(3, 4096): - if fd not in [7]: # trying to close 7 produces an illegal instruction on the Mac. + if fd in [7]: # trying to close 7 produces an illegal instruction on the Mac. + continue + try: os.close(fd) + except OSError: + pass else: os.closerange(3, 4096) ## just guessing on the maximum descriptor count.. From c210795cac7efbac661c958ddef6e7d177dfa6d1 Mon Sep 17 00:00:00 2001 From: Kenneth Lyons Date: Sun, 23 Jun 2019 15:24:36 -0700 Subject: [PATCH 2/2] Add test for exit function --- pyqtgraph/tests/test_exit_crash.py | 38 +++++++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/pyqtgraph/tests/test_exit_crash.py b/pyqtgraph/tests/test_exit_crash.py index de457d54..7c472104 100644 --- a/pyqtgraph/tests/test_exit_crash.py +++ b/pyqtgraph/tests/test_exit_crash.py @@ -1,7 +1,12 @@ -import os, sys, subprocess, tempfile +import os +import sys +import subprocess +import tempfile import pyqtgraph as pg import six import pytest +import textwrap +import time code = """ import sys @@ -14,6 +19,25 @@ w = pg.{classname}({args}) skipmessage = ('unclear why this test is failing. skipping until someone has' ' time to fix it') + +def call_with_timeout(*args, **kwargs): + """Mimic subprocess.call with timeout for python < 3.3""" + wait_per_poll = 0.1 + try: + timeout = kwargs.pop('timeout') + except KeyError: + timeout = 10 + + rc = None + p = subprocess.Popen(*args, **kwargs) + for i in range(int(timeout/wait_per_poll)): + rc = p.poll() + if rc is not None: + break + time.sleep(wait_per_poll) + return rc + + @pytest.mark.skipif(True, reason=skipmessage) def test_exit_crash(): # For each Widget subclass, run a simple python script that creates an @@ -40,3 +64,15 @@ def test_exit_crash(): assert proc.wait() == 0 os.remove(tmp) + + +def test_pg_exit(): + # test the pg.exit() function + code = textwrap.dedent(""" + import pyqtgraph as pg + app = pg.mkQApp() + pg.plot() + pg.exit() + """) + rc = call_with_timeout([sys.executable, '-c', code], timeout=5) + assert rc == 0