From 06714089fe3aeb72bee8de170fe42919aae7e9ff Mon Sep 17 00:00:00 2001 From: Jarrod Johnon Date: Mon, 29 Sep 2014 16:54:54 -0400 Subject: [PATCH] Recover from kill() while in command If a thread has kill() after incommand was set, but before it actually completed, then no fixup action will occur. Correct this by shrugging off incommand if it was set more than the maximum possible timeout before so that things can try to recover. An attempt was made with a Lock and 'with', but kill() did not see the lock actually release, so resort to expiring criteria instead. Change-Id: I67d47a1533bf2e46db4534d9c1465bea08de6f64 --- pyghmi/ipmi/private/session.py | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/pyghmi/ipmi/private/session.py b/pyghmi/ipmi/private/session.py index 0100bc6e..930f68d6 100644 --- a/pyghmi/ipmi/private/session.py +++ b/pyghmi/ipmi/private/session.py @@ -551,6 +551,21 @@ class Session(object): response['error'] = errorstr self.lastresponse = response + def _isincommand(self): + if self.incommand: + stillin = self.incommand - _monotonic_time() + if stillin > 0: + return stillin + return 0 + + def _getmaxtimeout(self): + cumulativetime = 0 + incrementtime = self.timeout + while incrementtime < self.maxtimeout: + cumulativetime += incrementtime + incrementtime += 1 + return cumulativetime + 1 + def raw_command(self, netfn, command, @@ -560,11 +575,11 @@ class Session(object): delay_xmit=None): if not self.logged: raise exc.IpmiException('Session no longer connected') - while self.incommand: - Session.wait_for_rsp() + while self._isincommand(): + Session.wait_for_rsp(self._isincommand()) if not self.logged: raise exc.IpmiException('Session no longer connected') - self.incommand = True + self.incommand = _monotonic_time() + self._getmaxtimeout() self.lastresponse = None self.ipmicallback = self._generic_callback self._send_ipmi_net_payload(netfn, command, data, @@ -946,7 +961,7 @@ class Session(object): for session, parms in cls.keepalive_sessions.iteritems(): # if the session is busy inside a command, defer invoking keepalive # until incommand is no longer the case - if parms['timeout'] < curtime and not session.incommand: + if parms['timeout'] < curtime and not session._isincommand(): cls.keepalive_sessions[session]['timeout'] = \ _monotonic_time() + 25 + (random.random() * 4.9) sessionstokeepalive.append(session)