[PYTHON-CRYPTO] m2crypto - close_wait when running echod_async

CARNES, MARK E (MARK) carnesm at LUCENT.COM
Tue Jun 22 01:54:19 CEST 2004


I've been looking at a server that is using the SSL.ssl_dispatcher and asyncore.dispatcher, and noticed
file descriptors that aren't being closed.  I went back and ran the echod_async example from the demo
directory and interestingly enough got the same result.

It looks like the socket is never being closed on the server side.  If I manually go do a self.socket.socket.close()
I can get it to go away, but it looks like it normally wouldn't call that method unless it goes through the __del__
method in Connection, and the reference count was never going to 0.

The end result is that the "Connection" class self references its own methods "self._write_bio", and "self._write_nbio",
which causes a circular reference and if you don't have garbage collection enabled, this object never gets collected.

I tested a variation of "Connection" where I just created a "self.mode" and corresponding "self.send", "self.write", "self.recv",
and "self.read" methods instead of using the method references.

Is there a better way to approach this problem?

Here's the code I changed

-------------------------------------------------------------------------------------------------------------------------------------------------------------

<<snip>>

class Connection:

    """An SSL connection."""

    def __init__(self, ctx, sock=None):
        self.ctx = ctx
        self.ssl = m2.ssl_new(self.ctx.ctx)
        if sock is not None:
            self.socket = sock
        else:
            self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        self._fileno = self.socket.fileno()
        self.mode = 0                                   # -- ADDED

   <<snip>>

    def setblocking(self, mode):
        """Set this connection's underlying socket to _mode_."""
        self.socket.setblocking(mode)
        self.mode = mode                                # -- ADDED
#        if mode:                                         -- REMOVED
#            self.send = self.write = self._write_bio     -- REMOVED
#            self.recv = self.read = self._read_bio       -- REMOVED
#        else:                                            -- REMOVED
#            self.send = self.write = self._write_nbio    -- REMOVED
#            self.recv = self.read = self._read_nbio      -- REMOVED

    # NEW METHODS FOLLOW

    def send(self, data):
        if self.mode:
            return self._write_bio(data)
        else:
            return self._write_nbio(data)

    def write(self, data):
        if self.mode:
            return self._write_bio(data)
        else:
            return self._write_nbio(data)

    def recv(self, size=1024):
        if self.mode:
            return self._read_bio(size)
        else:
            return self._read_nbio(size)

    def read(self, size=1024):
        if self.mode:
            return self._read_bio(size)
        else:
            return self._read_nbio(size)

    # END NEW METHODS

   <<snip>>




More information about the python-crypto mailing list