Search code examples
pythonpython-2.7socketserver

Dealing with dead sockets in rtmp.py


I am currently using rtmp.py for an RTMP live stream server. It works well, however several times a day, an individual with a presumably poor connection will vacate and leave their socket behind. Worse, nothing closes it except killing the entire server. Killcx won't even touch the connections. This is obviously not ideal. While the socket remains bound to, for example, /live1, other users cannot use this mount point.

The project is available on Github for source view. I am incredibly new to Python and in my research I believe the client connection falls hard which causes a failure to close(). I have tried to enlist the developer for help with no success. If anyone could help me implement a patch I will gladly submit it to the project page in hopes it will benefit others as well.

rtmp.py source

If you need additional information from me, please let me know. Thanks in advance!


Solution

  • The creator reached out to me. For future users who may have this problem, I am providing an answer that is working for me. The following changes were made to run(self): definition in rtmp.py. Adjust the values to your personal preference or use as-is. Commented as 'Issue 106'.

    def run(self):
    try:
        while True:
            sock, remote = (yield multitask.accept(self.sock))  # receive client TCP
            if sock == None:
                if _debug: print 'rtmp.Server accept(sock) returned None.'
                break
            if _debug: print 'connection received from', remote
            sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) # make it non-block
            sock.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1) # Issue #106
            sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPIDLE, 10) # Issue #106
            sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPINTVL, 10) # Issue #106
            sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPCNT, 2) # Issue #106
            client = Client(sock, self)
    except GeneratorExit: pass # terminate
    except:
        if _debug: print 'rtmp.Server exception ', (sys and sys.exc_info() or None)
    
    if (self.sock):
        try: self.sock.close(); self.sock = None
        except: pass
    if (self.queue):
        yield self.queue.put((None, None))
        self.queue = None