From 13072abc6b032a98f055182ed6a48cca463fd2f9 Mon Sep 17 00:00:00 2001 From: alexcjohnson Date: Wed, 4 May 2016 10:17:59 +0200 Subject: [PATCH 1/2] take out query timeout for all our servers by default --- qcodes/data/manager.py | 8 +++++--- qcodes/instrument/server.py | 9 ++++----- qcodes/utils/multiprocessing.py | 5 +++-- 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/qcodes/data/manager.py b/qcodes/data/manager.py index b7e0ee6985f3..ed160d300513 100644 --- a/qcodes/data/manager.py +++ b/qcodes/data/manager.py @@ -2,7 +2,7 @@ from queue import Empty from traceback import format_exc -from qcodes.utils.multiprocessing import ServerManager +from qcodes.utils.multiprocessing import ServerManager, SERVER_ERR def get_data_manager(only_existing=False): @@ -42,7 +42,7 @@ class DataManager(ServerManager): Written using multiprocessing Queue's, but should be easily extensible to other messaging systems ''' - def __init__(self, query_timeout=2): + def __init__(self): type(self).default = self super().__init__(name='DataServer', server_class=DataServer) @@ -122,7 +122,9 @@ def _reply(self, response): def _post_error(self, e): self._error_queue.put(format_exc()) - self._response_queue.put('ERR') # to short-circuit the timeout + # the caller is waiting on _response_queue, so put a signal there + # to say there's an error coming + self._response_queue.put(SERVER_ERR) ###################################################################### # query handlers # diff --git a/qcodes/instrument/server.py b/qcodes/instrument/server.py index d586556c014b..61b4a932f269 100644 --- a/qcodes/instrument/server.py +++ b/qcodes/instrument/server.py @@ -122,10 +122,7 @@ class InstrumentConnection: def __init__(self, manager, instrument_class, new_id, args, kwargs): self.manager = manager - # long timeout on the initial call, to allow slow errors - # (like visa timeout) to get back to us - info = manager.ask('new', instrument_class, new_id, args, kwargs, - timeout=20) + info = manager.ask('new', instrument_class, new_id, args, kwargs) for k, v in info.items(): setattr(self, k, v) @@ -190,7 +187,9 @@ def post_error(self, e, query=None): if query: e.args = e.args + ('error processing query ' + repr(query),) self._error_queue.put(format_exc()) - self._response_queue.put(SERVER_ERR) # to short-circuit timeout + # the caller is waiting on _response_queue, so put a signal there + # to say there's an error coming + self._response_queue.put(SERVER_ERR) def handle_halt(self, *args, **kwargs): ''' diff --git a/qcodes/utils/multiprocessing.py b/qcodes/utils/multiprocessing.py index 091108424943..807452d10d28 100644 --- a/qcodes/utils/multiprocessing.py +++ b/qcodes/utils/multiprocessing.py @@ -225,10 +225,11 @@ class ServerManager: name: the name of the server. Can include .format specs to insert all or part of the uuid - query_timeout: the default time to wait for responses + query_timeout: (default None) the default time to wait for responses kwargs: passed along to the server constructor ''' - def __init__(self, name, server_class, shared_attrs=None, query_timeout=2): + def __init__(self, name, server_class, shared_attrs=None, + query_timeout=None): self._query_queue = mp.Queue() self._response_queue = mp.Queue() self._error_queue = mp.Queue() From 6792bfc38d931fc39cb11492d38cd66752675aed Mon Sep 17 00:00:00 2001 From: alexcjohnson Date: Wed, 4 May 2016 10:33:48 +0200 Subject: [PATCH 2/2] slight simplification to how we handle server errors --- qcodes/tests/test_multiprocessing.py | 3 ++- qcodes/utils/multiprocessing.py | 18 ++++++++++++------ 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/qcodes/tests/test_multiprocessing.py b/qcodes/tests/test_multiprocessing.py index c6606e98c0dd..269272afefd4 100644 --- a/qcodes/tests/test_multiprocessing.py +++ b/qcodes/tests/test_multiprocessing.py @@ -396,7 +396,8 @@ def test_mechanics(self): ' OSError: your hard disk went floppy.') sm._error_queue.put(builtin_error_str) sm._response_queue.put(SERVER_ERR) - time.sleep(0.005) + while sm._error_queue.empty() or sm._response_queue.empty(): + time.sleep(0.005) with self.assertRaises(OSError): sm.ask('which way does the wind blow?') diff --git a/qcodes/utils/multiprocessing.py b/qcodes/utils/multiprocessing.py index 807452d10d28..1c2fbcadd899 100644 --- a/qcodes/utils/multiprocessing.py +++ b/qcodes/utils/multiprocessing.py @@ -277,7 +277,7 @@ def write(self, *query): self._query_queue.put(query) self._check_for_errors() - def _check_for_errors(self, expect_error=False): + def _check_for_errors(self, expect_error=False, query=None): if expect_error or not self._error_queue.empty(): # clear the response queue whenever there's an error # and give it a little time to flush first @@ -298,12 +298,18 @@ def _check_for_errors(self, expect_error=False): if err_type is None or not issubclass(err_type, Exception): err_type = RuntimeError + if query: + errhead += '\nwhile executing query: ' + repr(query) + raise err_type(errhead + '\n\n' + errstr) - def _check_response(self, timeout): + def _check_response(self, timeout, query=None): res = self._response_queue.get(timeout=timeout) if res == SERVER_ERR: - self._expect_error = True + # TODO: I think the way we're doing this now, I could get rid of + # _error_queue completely and just have errors and regular + # responses labeled differently in _response_queue + self._check_for_errors(expect_error=True, query=query) return res def ask(self, *query, timeout=None): @@ -324,16 +330,16 @@ def ask(self, *query, timeout=None): self._query_queue.put(query) try: - res = self._check_response(timeout) + res = self._check_response(timeout, query) while not self._response_queue.empty(): - res = self._check_response(timeout) + res = self._check_response(timeout, query) except Empty as e: if self._error_queue.empty(): # only raise if we're not about to find a deeper error raise e - self._check_for_errors(self._expect_error) + self._check_for_errors(query=query) return res