Commit 4fba95c6 authored by Antoine Millet's avatar Antoine Millet
Browse files

Fixed bug with server's client connection management

A server need to keep a list of connected clients to trigger their
shutdown when a global server shutdown is requested. To avoid memory
leaks with the client list, the list is composed of weakref. Problem:
connected RpcConnection can be collected because the application is not
required to keep a ref on each connection.

The problem was fixed by removing weakrefs. The list is cleaned of its
offline clients each time a new client is connected.
parent d4cc7d0e
Loading
Loading
Loading
Loading
+8 −11
Original line number Diff line number Diff line
@@ -54,6 +54,8 @@ class RpcServer(object):
        return RpcConnection(sock, self.loop, *self._conn_args, **self._conn_kw)

    def _handle(self, watcher, revents):
            # Collect offline connections:
            self._collect_connection()
            try:
                sock, address = self._sock.accept()
            except socket.error as err:
@@ -67,15 +69,13 @@ class RpcServer(object):
            conn = self._wrap(sock)
            self.register(conn)

    def _clean_conn(self, ref):
    def _collect_connection(self):
        '''
        Callback called by weakref when an object is about to be collected by
        garbage collector.
        Collect the offlines connections.
        '''
        try:
            self._clients.remove(ref)
        except KeyError:
            pass
        for conn in self._clients.copy():
            if not conn:
                self._clients.remove(conn)

#
# Public methods:
@@ -87,10 +87,7 @@ class RpcServer(object):

        :param conn: the connection to register.
        '''
        self._clients.add(weakref.ref(conn, self._clean_conn))
        gc.collect() # Force a manual garbage collection to avoid memory leak
                     # with RpcConnections. This is maybe not required but I
                     # need to read docs about python's gc and circular refs.
        self._clients.add(conn)

    def unregister(self, conn, shutdown=False):
        '''