aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin Braun <martin.braun@ettus.com>2020-12-07 17:46:05 +0100
committermichael-west <michael.west@ettus.com>2020-12-21 15:28:24 -0800
commit3b9ced8f07c068faf1f494ce170cb44edaa47075 (patch)
tree25feb579dbf78023a74e97f156358cc2df473487
parentdaa7ea5913bcbe2c63715eaab18b8c8f26608608 (diff)
downloaduhd-3b9ced8f07c068faf1f494ce170cb44edaa47075.tar.gz
uhd-3b9ced8f07c068faf1f494ce170cb44edaa47075.tar.bz2
uhd-3b9ced8f07c068faf1f494ce170cb44edaa47075.zip
mpm: rpc server: Fix unclaim sequence
Sequence is now: 1. Get _state lock 2. Kill reclaim timeout 3. Run deinit sequence 4. Clear claim token and session ID 5. Release _state lock Before, we were not locking the mutex, and the timer was killed after the deinit sequence. If the deinit sequence stalls for whatever reason, that doesn't have to cause a claimer loss to be reported. UHD will already have stopped the reclaim loop before unclaim() is called. In the stall case, it would also have been possible the to acquire a new claim while the deinit() is still running. This is prevented with the combination of actually acquiring the mutex (like claim() and reclaim() do) and moving the token/session ID clearing to the end.
-rw-r--r--mpm/python/usrp_mpm/rpc_server.py27
1 files changed, 19 insertions, 8 deletions
diff --git a/mpm/python/usrp_mpm/rpc_server.py b/mpm/python/usrp_mpm/rpc_server.py
index 1b840ee87..7fc292215 100644
--- a/mpm/python/usrp_mpm/rpc_server.py
+++ b/mpm/python/usrp_mpm/rpc_server.py
@@ -335,14 +335,18 @@ class MPMServer(RPCServer):
Resets and deinitalizes the periph manager as well.
"""
- self.log.debug("Releasing claim on session `{}'".format(
- self.session_id
- ))
- self._state.claim_status.value = False
- self._state.claim_token.value = b''
- self.session_id = None
+ self._state.lock.acquire()
+ self.log.debug(
+ "Deinitializing device and releasing claim on session `{}'"
+ .format(self.session_id))
+ # Disable unclaim timer, we're now finished with reclaim loops.
+ self._timer.kill()
+ # We might need to clear the method registry
if self.periph_manager.clear_rpc_registry_on_unclaim:
self.clear_method_registry()
+ # Now unclaim and deinit the device. We will try and catch any exception
+ # here, because the session is over and we have nowhere to send the
+ # exception.
try:
self.periph_manager.claimed = False
self.periph_manager.unclaim()
@@ -350,9 +354,16 @@ class MPMServer(RPCServer):
self.periph_manager.deinit()
except BaseException as ex:
self._last_error = str(ex)
- self.log.error("deinit() failed: %s", str(ex))
+ self.log.error("Deinitialization failed: %s", str(ex))
# Don't want to propagate this failure -- the session is over
- self._timer.kill()
+ finally:
+ # The finally clause is not strictly necessary, because we're catching
+ # everything and not returning, but it should be explicit that we
+ # must always clear the claim and the _state lock at this point.
+ self._state.claim_status.value = False
+ self._state.claim_token.value = b''
+ self._state.lock.release()
+ self.session_id = None
def unclaim(self, token):
"""