diff --git a/src/drivers/Socket.py b/src/drivers/Socket.py index 05da1c6c9..84039a1eb 100644 --- a/src/drivers/Socket.py +++ b/src/drivers/Socket.py @@ -56,7 +56,10 @@ except: class SocketDriver(drivers.IrcDriver, drivers.ServersMixin): + _instances = [] + _selecting = [False] # We want it to be mutable. def __init__(self, irc): + self._instances.append(self) self.irc = irc drivers.IrcDriver.__init__(self, irc) drivers.ServersMixin.__init__(self, irc) @@ -99,6 +102,8 @@ 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) + if self in self._instances: + self._instances.remove(self) try: self.conn.close() except: @@ -129,6 +134,32 @@ class SocketDriver(drivers.IrcDriver, drivers.ServersMixin): if self.zombie and not self.outbuffer: self._reallyDie() + @classmethod + def _select(cls): + if cls._selecting[0]: + return + print repr(map(lambda x:x.name(), cls._instances)) + try: + cls._selecting[0] = True + for inst in cls._instances: + # Do not use a list comprehension here, we have to edit the list + # and not to reassign it. + if inst.conn._sock.__class__ is socket._closedsocket: + cls._instances.remove(inst) + if not cls._instances: + return + rlist, wlist, xlist = select.select([x.conn for x in cls._instances], + [], [], conf.supybot.drivers.poll()) + for instance in cls._instances: + if instance.conn in rlist: + instance._read() + finally: + cls._selecting[0] = False + for instance in cls._instances: + if not instance.irc.zombie: + instance._sendIfMsgs() + + def run(self): now = time.time() if self.nextReconnectTime is not None and now > self.nextReconnectTime: @@ -141,6 +172,10 @@ class SocketDriver(drivers.IrcDriver, drivers.ServersMixin): time.sleep(conf.supybot.drivers.poll()) return self._sendIfMsgs() + self._select() + + def _read(self): + """Called by _select() when we can read data.""" try: self.inbuffer += self.conn.recv(1024) self.eagains = 0 # If we successfully recv'ed, we can reset this. @@ -173,6 +208,9 @@ class SocketDriver(drivers.IrcDriver, drivers.ServersMixin): self.nextReconnectTime = None if self.connected: drivers.log.reconnect(self.irc.network) + if self in self._instances: + self._instances.remove(self) + self.conn.shutdown(socket.SHUT_RDWR) self.conn.close() self.connected = False if reset: @@ -225,6 +263,7 @@ class SocketDriver(drivers.IrcDriver, drivers.ServersMixin): drivers.log.connectError(self.currentServer, e) self.scheduleReconnect() return + self._instances.append(self) def _checkAndWriteOrReconnect(self): self.writeCheckTime = None @@ -250,6 +289,8 @@ class SocketDriver(drivers.IrcDriver, drivers.ServersMixin): self.nextReconnectTime = when def die(self): + if self in self._instances: + self._instances.remove(self) self.zombie = True if self.nextReconnectTime is not None: self.nextReconnectTime = None @@ -259,6 +300,7 @@ class SocketDriver(drivers.IrcDriver, drivers.ServersMixin): def _reallyDie(self): if self.conn is not None: + self.conn.shutdown(socket.SHUT_RDWR) self.conn.close() drivers.IrcDriver.die(self) # self.irc.die() Kill off the ircs yourself, jerk!