From a278d17f2bec3697987cbd403594393a4fb30021 Mon Sep 17 00:00:00 2001 From: James Vega Date: Mon, 24 May 2010 23:36:29 -0400 Subject: [PATCH] Socket: Ensure driver is flagged as disconnected after a socket error. Users were occasionally hitting a situation where the socket had errored, causing a reconnect, but the socket wasn't closed nor the driver marked as disconnected. This resulted in run() continuing to try and use the driver, which would cause another error, schedule another reconnect, log an error, ad infinitum. Closes: Sf#2965530 Signed-off-by: James Vega --- src/drivers/Socket.py | 34 ++++++++++++++++++++++++---------- 1 file changed, 24 insertions(+), 10 deletions(-) diff --git a/src/drivers/Socket.py b/src/drivers/Socket.py index 86c6d6ada..6db605a59 100644 --- a/src/drivers/Socket.py +++ b/src/drivers/Socket.py @@ -1,5 +1,6 @@ ### # Copyright (c) 2002-2004, Jeremiah Fincher +# Copyright (c) 2010, James Vega # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -56,8 +57,9 @@ class SocketDriver(drivers.IrcDriver, drivers.ServersMixin): self.inbuffer = '' self.outbuffer = '' self.zombie = False - self.scheduled = None self.connected = False + self.writeCheckTime = None + self.nextReconnectTime = None self.resetDelay() # Only connect to non-SSL servers if self.networkGroup.get('ssl').value: @@ -87,6 +89,11 @@ class SocketDriver(drivers.IrcDriver, drivers.ServersMixin): # hasn't finished yet. We'll keep track of how many we get. if e.args[0] != 11 or self.eagains > 120: drivers.log.disconnect(self.currentServer, e) + try: + self.conn.close() + except: + pass + self.connected = False self.scheduleReconnect() else: log.debug('Got EAGAIN, current count: %s.', self.eagains) @@ -110,6 +117,11 @@ class SocketDriver(drivers.IrcDriver, drivers.ServersMixin): self._reallyDie() def run(self): + now = time.time() + if self.nextReconnectTime is not None and now > self.nextReconnectTime: + self.reconnect() + elif self.writeCheckTime is not None and now > self.writeCheckTime: + self._checkAndWriteOrReconnect() if not self.connected: # We sleep here because otherwise, if we're the only driver, we'll # spin at 100% CPU while we're disconnected. @@ -137,7 +149,7 @@ class SocketDriver(drivers.IrcDriver, drivers.ServersMixin): self.reconnect(reset=False, **kwargs) def reconnect(self, reset=True): - self.scheduled = None + self.nextReconnectTime = None if self.connected: drivers.log.reconnect(self.irc.network) self.conn.close() @@ -172,13 +184,14 @@ class SocketDriver(drivers.IrcDriver, drivers.ServersMixin): whenS = log.timestamp(when) drivers.log.debug('Connection in progress, scheduling ' 'connectedness check for %s', whenS) - schedule.addEvent(self._checkAndWriteOrReconnect, when) + self.writeCheckTime = when else: drivers.log.connectError(self.currentServer, e) self.scheduleReconnect() return def _checkAndWriteOrReconnect(self): + self.writeCheckTime = None drivers.log.debug('Checking whether we are connected.') (_, w, _) = select.select([], [self.conn], [], 0) if w: @@ -193,18 +206,19 @@ class SocketDriver(drivers.IrcDriver, drivers.ServersMixin): when = time.time() + self.getDelay() if not world.dying: drivers.log.reconnect(self.irc.network, when) - if self.scheduled: - drivers.log.error('Scheduling a second reconnect when one is ' - 'already scheduled. This is a bug; please ' + if self.nextReconnectTime: + drivers.log.error('Updating next reconnect time when one is ' + 'already present. This is a bug; please ' 'report it, with an explanation of what caused ' 'this to happen.') - schedule.removeEvent(self.scheduled) - self.scheduled = schedule.addEvent(self.reconnect, when) + self.nextReconnectTime = when def die(self): self.zombie = True - if self.scheduled: - schedule.removeEvent(self.scheduled) + if self.nextReconnectTime is not None: + self.nextReconnectTime = None + if self.writeCheckTime is not None: + self.writeCheckTime = None drivers.log.die(self.irc) def _reallyDie(self):