socket.accept()

Jordan Krushen jordan at krushen.com
Wed Feb 12 09:58:53 CET 2003


>     def shutdown(self):
>         self.die.set() # self.die is the event
>         s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
>         s.connect((Globals.ServerHostName,Globals.ServerPort))
>         s.close()
>         self.pool.shutdown()

Forgive me for stepping in the middle of a conversation;  I haven't seen the
start of this thread but I think I could offer some advice here, having
tried this lately myself.

I had code like that recently with an HTTPServer that would block in a call
to handle_request().  My shutdown function would set the flag, then do an
HTTP GET to its own port to force the call to handle_request() to finish.
There's a race condition here -- if someone else connects to the server
between you setting the flag and connecting yourself, the socket won't be
there when you try.  Even if it is there, connecting like this often tosses
all kinds of errors you'll have to trap (or at least it did in my case, peer
resets, etc. as a result of the proverbial rug being pulled out from
underneath it).

>   def run():
>      mysocket = socket.socket(blabla)
>    mysocket.bind(blabla)
>    mysocket.listen(1)
>    while 1:
>     newsocket, addr = mysocket.accept()
>     if self.die.isSet():
>      break

That's pretty much how I'd done it before, but it felt hackish and
inelegant.  Instead, I played with select.select() for the first time, and
it's incredibly small.  The following code is based on HTTPServer and its
handle_request() call, but it's essentially the same model as using
accept().

In this case, it's spawning a thread which is running a threaded HTTPServer.
All that's needed to shut it down is to call join(), which in something more
procedural could just be a function called shutdown().  By using select, I
know that the timeout will give me an average shutdown time for the server
of half a second, pending outstanding connections, which should be given
time to finish in my case.  Since I rewrote this, I haven't had any
unexpected socket errors :)


class Server(ThreadingMixIn, HTTPServer):
    def __init__(self):
        HTTPServer.__init__(self, ("0.0.0.0", 80), reqHandler)


class httpdThread(Thread):
    def __init__(self, timeout=1):
        self.timeout = timeout
        self._stopevent = Event()

        Thread.__init__(self)

    def run(self):
        svr = Server()
        svrfd = svr.fileno()

        while not self._stopevent.isSet():
            ready = select.select([svrfd], [], [], self.timeout)
            if svrfd in ready[0]:
                svr.handle_request()

    def join(self, timeout=None):
        self._stopevent.set()

        Thread.join(self, timeout)






More information about the Python-list mailing list