Skip to content

Socket is not closed after client left #119

Description

@vzarutskiy

Python-dbg detected warning during websocket server working:

[INFO 2023.04.12 21:14:58 Thread-2:warnings.py:30][_showwarnmsg_impl]: ****:164: ResourceWarning: unclosed <socket.socket [closed] fd=11, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0>
if check_str in list(self.check_pattern_callbacks.keys()):
Object allocated at (most recent call last):
File "/usr/lib/python3.8/threading.py", lineno 890
self._bootstrap_inner()
File "/usr/lib/python3.8/threading.py", lineno 932
self.run()
File "/home/user/.local/lib/python3.8/site-packages/websocket_server/thread.py", lineno 27
self._target(*self._args, **self._kwargs)
File "/usr/lib/python3.8/socketserver.py", lineno 237
self._handle_request_noblock()
File "/usr/lib/python3.8/socketserver.py", lineno 311
request, client_address = self.get_request()
File "/usr/lib/python3.8/socketserver.py", lineno 502
return self.socket.accept()
File "/usr/lib/python3.8/socket.py", lineno 293
sock = socket(self.family, self.type, self.proto, fileno=fd)

Real socket closing happens in case where self._io_refs = 0 (socket.py):

    def close(self):
        # This function should not reference any globals. See issue #808164.
        self._closed = True
        if self._io_refs <= 0:
            self._real_close()

self._io_refs is used in makefile (socket.py):

def makefile(self, mode="r", buffering=None, *,
             encoding=None, errors=None, newline=None):
    ...
    self._io_refs += 1
    ...
    return text

makefile is used in "setup" from StreamRequestHandler (socketserver.py):

class StreamRequestHandler(BaseRequestHandler):
    ...
    def setup(self):
        ...
        self.rfile = self.connection.makefile('rb', self.rbufsize)
        if self.wbufsize == 0:
            self.wfile = _SocketWriter(self.connection)
        else:
            self.wfile = self.connection.makefile('wb', self.wbufsize)

    def finish(self):
        ...
        self.wfile.close()
        self.rfile.close()

Stream closing, which was opened by makefile happens in "finish" method of StreamRequestHandler, but this method does not execute in WebSocketHandler, only StreamRequestHandler.setup(self):

class WebSocketHandler(StreamRequestHandler):
    ...
    def setup(self):
        StreamRequestHandler.setup(self)
        self.keep_alive = True
        self.handshake_done = False
        self.valid_client = False
    ...
    def finish(self):
        self.server._client_left_(self)

Possible fix:

def finish(self):
    StreamRequestHandler.finish(self)
    self.server._client_left_(self)

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions