comparison mercurial/commandserver.py @ 40875:e7110f44ee2d

commandserver: pass around option to hook repo instance creation This is necessary to wrap a repo instance so the master process will be notified on repo.close().
author Yuya Nishihara <yuya@tcha.org>
date Wed, 31 Oct 2018 21:57:11 +0900
parents 25e9089c7686
children dc9901558e3c
comparison
equal deleted inserted replaced
40874:348352658e4b 40875:e7110f44ee2d
194 class server(object): 194 class server(object):
195 """ 195 """
196 Listens for commands on fin, runs them and writes the output on a channel 196 Listens for commands on fin, runs them and writes the output on a channel
197 based stream to fout. 197 based stream to fout.
198 """ 198 """
199 def __init__(self, ui, repo, fin, fout): 199 def __init__(self, ui, repo, fin, fout, prereposetups=None):
200 self.cwd = encoding.getcwd() 200 self.cwd = encoding.getcwd()
201 201
202 if repo: 202 if repo:
203 # the ui here is really the repo ui so take its baseui so we don't 203 # the ui here is really the repo ui so take its baseui so we don't
204 # end up with its local configuration 204 # end up with its local configuration
206 self.repo = repo 206 self.repo = repo
207 self.repoui = repo.ui 207 self.repoui = repo.ui
208 else: 208 else:
209 self.ui = ui 209 self.ui = ui
210 self.repo = self.repoui = None 210 self.repo = self.repoui = None
211 self._prereposetups = prereposetups
211 212
212 self.cdebug = channeledoutput(fout, 'd') 213 self.cdebug = channeledoutput(fout, 'd')
213 self.cerr = channeledoutput(fout, 'e') 214 self.cerr = channeledoutput(fout, 'e')
214 self.cout = channeledoutput(fout, 'o') 215 self.cout = channeledoutput(fout, 'o')
215 self.cin = channeledinput(fin, fout, 'I') 216 self.cin = channeledinput(fin, fout, 'I')
292 # enforced only if cin is a channel. 293 # enforced only if cin is a channel.
293 if not util.safehasattr(self.cin, 'fileno'): 294 if not util.safehasattr(self.cin, 'fileno'):
294 ui.setconfig('ui', 'nontty', 'true', 'commandserver') 295 ui.setconfig('ui', 'nontty', 'true', 'commandserver')
295 296
296 req = dispatch.request(args[:], copiedui, self.repo, self.cin, 297 req = dispatch.request(args[:], copiedui, self.repo, self.cin,
297 self.cout, self.cerr, self.cmsg) 298 self.cout, self.cerr, self.cmsg,
299 prereposetups=self._prereposetups)
298 300
299 try: 301 try:
300 ret = dispatch.dispatch(req) & 255 302 ret = dispatch.dispatch(req) & 255
301 self.cresult.write(struct.pack('>i', int(ret))) 303 self.cresult.write(struct.pack('>i', int(ret)))
302 finally: 304 finally:
418 os.setpgid(0, 0) 420 os.setpgid(0, 0)
419 # change random state otherwise forked request handlers would have a 421 # change random state otherwise forked request handlers would have a
420 # same state inherited from parent. 422 # same state inherited from parent.
421 random.seed() 423 random.seed()
422 424
423 def _serverequest(ui, repo, conn, createcmdserver): 425 def _serverequest(ui, repo, conn, createcmdserver, prereposetups):
424 fin = conn.makefile(r'rb') 426 fin = conn.makefile(r'rb')
425 fout = conn.makefile(r'wb') 427 fout = conn.makefile(r'wb')
426 sv = None 428 sv = None
427 try: 429 try:
428 sv = createcmdserver(repo, conn, fin, fout) 430 sv = createcmdserver(repo, conn, fin, fout, prereposetups)
429 try: 431 try:
430 sv.serve() 432 sv.serve()
431 # handle exceptions that may be raised by command server. most of 433 # handle exceptions that may be raised by command server. most of
432 # known exceptions are caught by dispatch. 434 # known exceptions are caught by dispatch.
433 except error.Abort as inst: 435 except error.Abort as inst:
482 return False 484 return False
483 485
484 def newconnection(self): 486 def newconnection(self):
485 """Called when main process notices new connection""" 487 """Called when main process notices new connection"""
486 488
487 def createcmdserver(self, repo, conn, fin, fout): 489 def createcmdserver(self, repo, conn, fin, fout, prereposetups):
488 """Create new command server instance; called in the process that 490 """Create new command server instance; called in the process that
489 serves for the current connection""" 491 serves for the current connection"""
490 return server(self.ui, repo, fin, fout) 492 return server(self.ui, repo, fin, fout, prereposetups)
491 493
492 class unixforkingservice(object): 494 class unixforkingservice(object):
493 """ 495 """
494 Listens on unix domain socket and forks server per connection 496 Listens on unix domain socket and forks server per connection
495 """ 497 """
617 def _runworker(self, conn): 619 def _runworker(self, conn):
618 signal.signal(signal.SIGCHLD, self._oldsigchldhandler) 620 signal.signal(signal.SIGCHLD, self._oldsigchldhandler)
619 _initworkerprocess() 621 _initworkerprocess()
620 h = self._servicehandler 622 h = self._servicehandler
621 try: 623 try:
622 _serverequest(self.ui, self.repo, conn, h.createcmdserver) 624 _serverequest(self.ui, self.repo, conn, h.createcmdserver,
625 prereposetups=None) # TODO: pass in hook functions
623 finally: 626 finally:
624 gc.collect() # trigger __del__ since worker process uses os._exit 627 gc.collect() # trigger __del__ since worker process uses os._exit