336 return sv.serve() |
336 return sv.serve() |
337 finally: |
337 finally: |
338 sv.cleanup() |
338 sv.cleanup() |
339 _restoreio(ui, fin, fout) |
339 _restoreio(ui, fin, fout) |
340 |
340 |
341 class _requesthandler(socketserver.StreamRequestHandler): |
341 class _requesthandler(socketserver.BaseRequestHandler): |
342 def handle(self): |
342 def handle(self): |
343 # use a different process group from the master process, making this |
343 # use a different process group from the master process, making this |
344 # process pass kernel "is_current_pgrp_orphaned" check so signals like |
344 # process pass kernel "is_current_pgrp_orphaned" check so signals like |
345 # SIGTSTP, SIGTTIN, SIGTTOU are not ignored. |
345 # SIGTSTP, SIGTTIN, SIGTTOU are not ignored. |
346 os.setpgid(0, 0) |
346 os.setpgid(0, 0) |
347 # change random state otherwise forked request handlers would have a |
347 # change random state otherwise forked request handlers would have a |
348 # same state inherited from parent. |
348 # same state inherited from parent. |
349 random.seed() |
349 random.seed() |
350 ui = self.server.ui |
350 ui = self.server.ui |
|
351 |
|
352 conn = self.request |
|
353 fin = conn.makefile('rb') |
|
354 fout = conn.makefile('wb') |
351 sv = None |
355 sv = None |
352 try: |
356 try: |
353 sv = self._createcmdserver() |
357 sv = self._createcmdserver(conn, fin, fout) |
354 try: |
358 try: |
355 sv.serve() |
359 sv.serve() |
356 # handle exceptions that may be raised by command server. most of |
360 # handle exceptions that may be raised by command server. most of |
357 # known exceptions are caught by dispatch. |
361 # known exceptions are caught by dispatch. |
358 except error.Abort as inst: |
362 except error.Abort as inst: |
368 # also write traceback to error channel. otherwise client cannot |
372 # also write traceback to error channel. otherwise client cannot |
369 # see it because it is written to server's stderr by default. |
373 # see it because it is written to server's stderr by default. |
370 if sv: |
374 if sv: |
371 cerr = sv.cerr |
375 cerr = sv.cerr |
372 else: |
376 else: |
373 cerr = channeledoutput(self.wfile, 'e') |
377 cerr = channeledoutput(fout, 'e') |
374 traceback.print_exc(file=cerr) |
378 traceback.print_exc(file=cerr) |
375 raise |
379 raise |
376 finally: |
380 finally: |
|
381 fin.close() |
|
382 try: |
|
383 fout.close() # implicit flush() may cause another EPIPE |
|
384 except IOError as inst: |
|
385 if inst.errno != errno.EPIPE: |
|
386 raise |
377 # trigger __del__ since ForkingMixIn uses os._exit |
387 # trigger __del__ since ForkingMixIn uses os._exit |
378 gc.collect() |
388 gc.collect() |
379 |
389 |
380 def _createcmdserver(self): |
390 def _createcmdserver(self, conn, fin, fout): |
381 ui = self.server.ui |
391 ui = self.server.ui |
382 repo = self.server.repo |
392 repo = self.server.repo |
383 return server(ui, repo, self.rfile, self.wfile) |
393 return server(ui, repo, fin, fout) |
384 |
394 |
385 class unixservice(object): |
395 class unixservice(object): |
386 """ |
396 """ |
387 Listens on unix domain socket and forks server per connection |
397 Listens on unix domain socket and forks server per connection |
388 """ |
398 """ |