[PATCH 1 of 6] socketserver: backport a less sucky socketserver from python 3.5.1

Jun Wu quark at fb.com
Thu May 12 19:12:54 EDT 2016


On 05/12/2016 10:47 PM, Jun Wu wrote:
> On 05/12/2016 12:02 AM, Yuya Nishihara wrote:
>>> I think SocketServer won't make that harder, is it?
>>
>> Yeah, I guess it will be harder to write a PreForkingMixIn since IMHO
>> pre-forking works very differently from fork-per-request or
>> thread-per-request.
>>
>> That's why I don't care for the SocketServer compatibility.
>
> I tried to implement the preforking model in a quick and dirty way, and got this:
>
>   https://gist.github.com/quark-zju/015c448b548bc6fbad4105868e2028ac
>
> which does not look bad and socketserver does save a lot lines here.
> Most of the lines are necessary to implement a preforked server anyway.
>
> (I haven't tried to convert them into MixIns but it's at least possible
> for the master).

The MixIn version is 34 lines (and I have updated the gist):

     class PreforkMixIn:
         max_nchildren = 3
         children = None

         def spawn_workers_forever(self, interval=0.5):
             if self.children is None:
                 self.children = set()
             while not os.path.exists('/tmp/exit'):
                 self.create_workers()
                 self.reap_workers()
                 time.sleep(interval)

         def create_workers(self, interval=0.5):
             while len(self.children) < self.max_nchildren:
                 pid = os.fork()
                 assert pid >= 0
                 if pid == 0:
                     try:
                         self.serve_forever()
                     finally:
                         sys.exit(0)
                 else:
                     self.children.add(pid)
                     time.sleep(interval)

         def reap_workers(self):
             for pid in self.children.copy():
                 try:
                     pid, _ = os.waitpid(pid, os.WNOHANG)
                     self.children.discard(pid)
                 except ChildProcessError:
                     self.children.discard(pid)
                 except OSError:
                     pass

To use it:

     class echohandler(socketserver.StreamRequestHandler):
         def handle(self):
             while 1:
                 data = self.rfile.read(1)
                 if not data:
                     break
                 self.wfile.write(data)

     class myserver(PreforkMixIn, socketserver.UnixStreamServer):
         pass

     myserver('/tmp/server', echohandler).spawn_workers_forever()

Pretty neat, isn't it?



More information about the Mercurial-devel mailing list