diff options
author | Martin Braun <martin.braun@ettus.com> | 2020-12-07 17:46:05 +0100 |
---|---|---|
committer | michael-west <michael.west@ettus.com> | 2020-12-21 15:28:24 -0800 |
commit | 3b9ced8f07c068faf1f494ce170cb44edaa47075 (patch) | |
tree | 25feb579dbf78023a74e97f156358cc2df473487 | |
parent | daa7ea5913bcbe2c63715eaab18b8c8f26608608 (diff) | |
download | uhd-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.py | 27 |
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): """ |