Skip to content Skip to sidebar Skip to footer

Python Socket Accept Blocks - Prevents App From Quitting

I've written a very simple python class which waits for connections on a socket. The intention is to stick this class into an existing app and asyncronously send data to connecting

Solution 1:

Add self.setDaemon(True) to the __init__ before self.start().

(In Python 2.6 and later, self.daemon = True is preferred).

The key idea is explained here:

The entire Python program exits when no alive non-daemon threads are left.

So, you need to make "daemons" of those threads who should not keep the whole process alive just by being alive themselves. The main thread is always non-daemon, by the way.


Solution 2:

I don't recommend the setDaemon feature for normal shutdown. It's sloppy; instead of having a clean shutdown path for threads, it simply kills the thread with no chance for cleanup. It's good to set it, so your program doesn't get stuck if the main thread exits unexpectedly, but it's not a good normal shutdown path except for quick hacks.

import sys, os, socket, threading, time, select

class Server(threading.Thread):
    def __init__(self, i_port):
        threading.Thread.__init__(self)
        self.setDaemon(True)
        self.quitting = False
        self.serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.serversocket.bind((socket.gethostname(), i_port))
        self.serversocket.listen(5)
        self.start()

    def shutdown(self):
        if self.quitting:
            return

        self.quitting = True
        self.join()

    def run(self):
        # Wait for connection
        while not self.quitting:
            rr,rw,err = select.select([self.serversocket],[],[], 1)
            print rr
            if rr:
                (clientsocket, address) = self.serversocket.accept()
                clientsocket.close()

        print "shutting down"
        self.serversocket.close()

def main():
    a = Server(6543)
    try:
        time.sleep(4)
    finally:
        a.shutdown()

if __name__=='__main__':
  main()

Note that this will delay for up to a second after calling shutdown(), which is poor behavior. This is normally easy to fix: create a wakeup pipe() that you can write to, and include it in the select; but although this is very basic, I couldn't find any way to do this in Python. (os.pipe() returns file descriptors, not file objects that we can write to.) I havn't dig deeper, since it's tangental to the question.


Post a Comment for "Python Socket Accept Blocks - Prevents App From Quitting"