comparison mercurial/commandserver.py @ 29586:42cdba9cfee4

commandserver: separate initialization and cleanup of forked process Separated _initworkerprocess() and _serverequest() can be reused when implementing a prefork service.
author Yuya Nishihara <yuya@tcha.org>
date Sun, 22 May 2016 13:53:32 +0900
parents 6ed452d0f1f1
children 536eec443b4a
comparison
equal deleted inserted replaced
29585:6ed452d0f1f1 29586:42cdba9cfee4
340 return sv.serve() 340 return sv.serve()
341 finally: 341 finally:
342 sv.cleanup() 342 sv.cleanup()
343 _restoreio(ui, fin, fout) 343 _restoreio(ui, fin, fout)
344 344
345 def _serverequest(ui, repo, conn, createcmdserver): 345 def _initworkerprocess():
346 # use a different process group from the master process, making this 346 # use a different process group from the master process, making this
347 # process pass kernel "is_current_pgrp_orphaned" check so signals like 347 # process pass kernel "is_current_pgrp_orphaned" check so signals like
348 # SIGTSTP, SIGTTIN, SIGTTOU are not ignored. 348 # SIGTSTP, SIGTTIN, SIGTTOU are not ignored.
349 os.setpgid(0, 0) 349 os.setpgid(0, 0)
350 # change random state otherwise forked request handlers would have a 350 # change random state otherwise forked request handlers would have a
351 # same state inherited from parent. 351 # same state inherited from parent.
352 random.seed() 352 random.seed()
353 353
354 def _serverequest(ui, repo, conn, createcmdserver):
354 fin = conn.makefile('rb') 355 fin = conn.makefile('rb')
355 fout = conn.makefile('wb') 356 fout = conn.makefile('wb')
356 sv = None 357 sv = None
357 try: 358 try:
358 sv = createcmdserver(repo, conn, fin, fout) 359 sv = createcmdserver(repo, conn, fin, fout)
383 try: 384 try:
384 fout.close() # implicit flush() may cause another EPIPE 385 fout.close() # implicit flush() may cause another EPIPE
385 except IOError as inst: 386 except IOError as inst:
386 if inst.errno != errno.EPIPE: 387 if inst.errno != errno.EPIPE:
387 raise 388 raise
388 # trigger __del__ since ForkingMixIn uses os._exit
389 gc.collect()
390 389
391 class unixservicehandler(object): 390 class unixservicehandler(object):
392 """Set of pluggable operations for unix-mode services 391 """Set of pluggable operations for unix-mode services
393 392
394 Almost all methods except for createcmdserver() are called in the main 393 Almost all methods except for createcmdserver() are called in the main
515 self.ui.debug('worker process exited (pid=%d)\n' % pid) 514 self.ui.debug('worker process exited (pid=%d)\n' % pid)
516 self._workerpids.discard(pid) 515 self._workerpids.discard(pid)
517 516
518 def _serveworker(self, conn): 517 def _serveworker(self, conn):
519 signal.signal(signal.SIGCHLD, self._oldsigchldhandler) 518 signal.signal(signal.SIGCHLD, self._oldsigchldhandler)
519 _initworkerprocess()
520 h = self._servicehandler 520 h = self._servicehandler
521 _serverequest(self.ui, self.repo, conn, h.createcmdserver) 521 try:
522 _serverequest(self.ui, self.repo, conn, h.createcmdserver)
523 finally:
524 gc.collect() # trigger __del__ since worker process uses os._exit
522 525
523 _servicemap = { 526 _servicemap = {
524 'pipe': pipeservice, 527 'pipe': pipeservice,
525 'unix': unixforkingservice, 528 'unix': unixforkingservice,
526 } 529 }