lingering sockets in CLOSE_WAIT state

Kevin Le avatarKevin Le created an issue

If you open several websockets then close them, they linger in a CLOSE_WAIT state, which occupies a file descriptor. For a process handling multiple clients connecting and reconnecting, you hit the file descriptor limit pretty quickly.

Is there any way to teardown these lingering connections?

Comments (9)

  1. Kevin Le

    Ah, interestingly enough, if I don't explicitly call close() on the socket, the file descriptor gets cleaned up during the garbage collection process.

    I'm still curious why it lingers if you explicitly close it.

  2. Greg Taylor

    I've noticed this too. It would be really nice if the websocket.send() method gave a hint that the socket is no longer connected so I can websocket.close() it, or something like that. I've got a lot of open connections hanging out, as well.

  3. Kevin Le

    I can no longer reproduce this. I haven't changed my version of gevent-websockets, so something about my application environment changed such that this is no longer an issue for me. I'm keeping an eye on it though.

  4. Jason Pellerin

    I can reproduce this easily with gevent-websocket tip, gevent-socketio rc3, and womack (https://github.com/leapfrogdevelopment/womack). Install those in a virtualenv, start a womack server, browse to localhost:8111/test.html, then close the tab (but not the browser). For me on Ubuntu 12.04 with most recent chrome and firefox stable releases, I always see a socket linger in CLOSE_WAIT. I was able to fix it locally by modifying WebSocketHybi._close:

        def _close(self):
            log.debug('inner _close called')
            if self.socket is not None:
                self.socket.shutdown(SHUT_RDWR) # added
                if not self._reading:
                    log.debug('actually calling fobj.close')
                    self.fobj.close()
    
                self.socket.close() # added
                self.socket = None # moved
                self._write = None
                self.fobj = None
    

    ... but I really don't know what I'm doing this far into the guts of websocket, so that may be totally crazy or wrong or both.

  5. Jason Pellerin

    Having looked a little more, it seems to me that the issue is probably specific to python 2.6 and older, and due to makefile() in python_fixes returning a socket._fileobject with close set to False -- the file object gets closed when the websocket closes, but the fileobject's socket does not. This change fixes the leaking fds for me:

    # ...
    else:
        def makefile(socket):
            # XXX on python3 enable buffering
            sock = socket.makefile()
            sock._close = True
            return sock
    
  6. Log in to comment
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.