From 657b75cc86855f15e1f71ded266a0387a6648d9e Mon Sep 17 00:00:00 2001 From: Jarrod Johnson Date: Mon, 12 Sep 2016 15:48:25 -0400 Subject: [PATCH] Fix multiple console object behavior Software could end up creating duplicate console objects. Try to adapt by assuring only the most recently created one is the sol_handler (by using existing sol_handler to reach old instance). Also unhook a keepalive when we go broken. When the ipmi session breaks, notify all custom keepalives active, rather than just the one currently holding SOL session. Some of these changes in principle may be duplicate, but it should be more robust this way. Change-Id: Id8d3869917de3db723a4b6a79e02643345111b3a --- pyghmi/ipmi/console.py | 10 ++++++++++ pyghmi/ipmi/private/session.py | 10 ++++++++-- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/pyghmi/ipmi/console.py b/pyghmi/ipmi/console.py index 7aba51c9..3efbd9b7 100644 --- a/pyghmi/ipmi/console.py +++ b/pyghmi/ipmi/console.py @@ -131,6 +131,10 @@ class Console(object): #code anyway... #NOTE(jbjohnso): #We will use a special purpose keepalive + if self.ipmi_session.sol_handler is not None: + # If there is erroneously another SOL handler already, notify + # it of newly established session + self.ipmi_session.sol_handler({'error': 'Session Disconnected'}) self.keepaliveid = self.ipmi_session.register_keepalive( cmd={'netfn': 6, 'command': 0x4b, 'data': (1, 1)}, callback=self._got_payload_instance_info) @@ -270,6 +274,12 @@ class Console(object): def _print_error(self, error): self.broken = True + if self.ipmi_session: + self.ipmi_session.unregister_keepalive(self.keepaliveid) + if (self.ipmi_session.sol_handler and + self.ipmi_session.sol_handler.__self__ is self): + self.ipmi_session.sol_handler = None + self.ipmi_session = None if type(error) == dict: self._print_data(error) else: diff --git a/pyghmi/ipmi/private/session.py b/pyghmi/ipmi/private/session.py index c71be8d1..caba4a8e 100644 --- a/pyghmi/ipmi/private/session.py +++ b/pyghmi/ipmi/private/session.py @@ -496,6 +496,14 @@ class Session(object): if self.logged: self.logged = 0 # mark session as busted self.logging = False + for ka in list(self._customkeepalives): + # Be thorough and notify parties through their custom + # keepalives. In practice, this *should* be the same, but + # if a code somehow makes duplicate SOL handlers, + # this would notify all the handlers rather than just the + # last one to take ownership + self._customkeepalives[ka][1]( + {'error': 'Session Disconnected'}) self._customkeepalives = None if not self.broken: self.socketpool[self.socket] -= 1 @@ -506,8 +514,6 @@ class Session(object): for sockaddr in self.allsockaddrs: if sockaddr in Session.bmc_handlers: del Session.bmc_handlers[sockaddr] - if self.sol_handler: - self.sol_handler({'error': 'Session Disconnected'}) elif not self.broken: self.broken = True self.socketpool[self.socket] -= 1