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 } |