diff options
author | Lars Amsel <lars.amsel@ni.com> | 2021-04-19 11:18:27 +0200 |
---|---|---|
committer | Aaron Rossetto <aaron.rossetto@ni.com> | 2021-06-03 09:34:20 -0500 |
commit | 1f001f2c292b794c42e1ec7a663cfe75e7851f3a (patch) | |
tree | a1f3215bb60bf0a3b036f6a90fe4790748361f3a /host/python | |
parent | 2a5f0ea13e6d7d00798d6547e1170ff85d4aa42a (diff) | |
download | uhd-1f001f2c292b794c42e1ec7a663cfe75e7851f3a.tar.gz uhd-1f001f2c292b794c42e1ec7a663cfe75e7851f3a.tar.bz2 uhd-1f001f2c292b794c42e1ec7a663cfe75e7851f3a.zip |
python: Add graceful exit of claim loop on SIGTERM
Diffstat (limited to 'host/python')
-rw-r--r-- | host/python/uhd/utils/mpmtools.py | 77 |
1 files changed, 58 insertions, 19 deletions
diff --git a/host/python/uhd/utils/mpmtools.py b/host/python/uhd/utils/mpmtools.py index c2324a2d5..90dd63be0 100644 --- a/host/python/uhd/utils/mpmtools.py +++ b/host/python/uhd/utils/mpmtools.py @@ -8,9 +8,9 @@ RPC/MPM utilities for debugging USRPs """ from enum import Enum -import time import multiprocessing - +import queue +import signal from mprpc import RPCClient from mprpc.exceptions import RPCError @@ -26,17 +26,38 @@ def _claim_loop(host, port, cmd_q, token_q): exit. The token queue is used to read back the current token. """ + + def _sig_term_handler(_signo, _stack): + """ + gracefully terminate claim loop + """ + cmd_q.put("exit") + command = None token = None exit_loop = False + + signal.signal(signal.SIGTERM, _sig_term_handler) + client = RPCClient(host, port, pack_params={'use_bin_type': True}) try: while not exit_loop: - if token and not command: - client.call('reclaim', token) - elif command == 'claim': + try: + command = cmd_q.get(True, 1) + except queue.Empty: + # if we do not receive a command, reclaim device + if token: + client.call('reclaim', token) + continue + + if command == 'claim': if not token: - token = client.call('claim', 'UHD') + try: + token = client.call('claim', 'UHD') + except RPCError as ex: + # catch RPC errors here so the loop keeps running + # and token queue receives an (empty) value + print(str(ex)) else: print("Already have claim") token_q.put(token) @@ -51,10 +72,6 @@ def _claim_loop(host, port, cmd_q, token_q): token = None token_q.put(None) exit_loop = True - time.sleep(1) - command = None - if not cmd_q.empty(): - command = cmd_q.get(False) except RPCError as ex: print("Unexpected RPC error in claimer loop!") print(str(ex)) @@ -72,6 +89,7 @@ class MPMClaimer: name="Claimer Loop", args=(host, port, self._cmd_q, self._token_q) ) + self._claim_loop.daemon = True self._claim_loop.start() def exit(self): @@ -87,14 +105,16 @@ class MPMClaimer: Unclaim device. """ self._cmd_q.put('unclaim') - self.token = None + self.token = self._token_q.get(True, 1) def claim(self): """ Claim device. """ self._cmd_q.put('claim') - self.token = self._token_q.get(True, 5.0) + self.token = self._token_q.get(True, 1) + if not self.token: + raise RuntimeError("Failed to claim device") def get_token(self): """ @@ -105,6 +125,9 @@ class MPMClaimer: return self.token class InitMode(Enum): + """ + Init modes for MPM session + """ Hijack = 1 Claim = 2 Noclaim = 3 @@ -116,17 +139,11 @@ class MPMClient: """ MPM RPC Client: Will make all MPM commands accessible as Python methods. """ - def __init__(self, init_mode, host, port, token=None): + def __init__(self, init_mode, host, port=MPM_RPC_PORT, token=None): assert isinstance(init_mode, InitMode) print("[MPMRPC] Attempting to connect to {host}:{port}...".format( host=host, port=port )) - try: - self._client = RPCClient(host, port, pack_params={'use_bin_type': True}) - print("[MPMRPC] Connection successful.") - except Exception as ex: - print("[MPMRPC] Connection refused: {}".format(ex)) - raise RuntimeError("RPC connection refused.") self._remote_methods = [] if init_mode == InitMode.Hijack: assert token @@ -135,12 +152,34 @@ class MPMClient: self._claimer = MPMClaimer(host, port) self._claimer.claim() self._token = self._claimer.token + + try: + self._client = RPCClient(host, port, pack_params={'use_bin_type': True}) + print("[MPMRPC] Connection successful.") + except Exception as ex: + print("[MPMRPC] Connection refused: {}".format(ex)) + raise RuntimeError("RPC connection refused.") print("[MPMRPC] Getting methods...") methods = self._client.call('list_methods') for method in methods: self._add_command(*method) print("[MPMRPC] Added {} methods.".format(len(methods))) + def __del__(self): + if hasattr(self, '_claimer'): + self._claimer.exit() + + def claim(self): + """ + Use claimer (instead of RPC method) to claim MPM device + """ + self._claimer.claim() + + def unclaim(self): + """ + Use claimer (instead of RPC method) to unclaim MPM device + """ + self._claimer.unclaim() def _add_command(self, command, docs, requires_token): """ |