comparison mercurial/commandserver.py @ 37123:0216232f21ab

procutil: move protectio/restoreio from commandserver Some variants of this will be useful for stdio-based servers such as sshserver.
author Yuya Nishihara <yuya@tcha.org>
date Sun, 25 Mar 2018 11:40:30 +0900
parents 4f742c2cb837
children 6715e8035b4f
comparison
equal deleted inserted replaced
37122:4f742c2cb837 37123:0216232f21ab
304 # its request 304 # its request
305 return 1 305 return 1
306 306
307 return 0 307 return 0
308 308
309 def _protectio(uin, uout):
310 """Duplicate streams and redirect original to null if (uin, uout) are
311 stdio
312
313 Returns (fin, fout) which point to the original (uin, uout) fds, but
314 may be copy of (uin, uout). The returned streams can be considered
315 "owned" in that print(), exec(), etc. never reach to them.
316 """
317 uout.flush()
318 newfiles = []
319 nullfd = os.open(os.devnull, os.O_RDWR)
320 for f, sysf, mode in [(uin, procutil.stdin, r'rb'),
321 (uout, procutil.stdout, r'wb')]:
322 if f is sysf:
323 newfd = os.dup(f.fileno())
324 os.dup2(nullfd, f.fileno())
325 f = os.fdopen(newfd, mode)
326 newfiles.append(f)
327 os.close(nullfd)
328 return tuple(newfiles)
329
330 def _restoreio(uin, uout, fin, fout):
331 """Restore (uin, uout) streams from possibly duplicated (fin, fout)"""
332 uout.flush()
333 for f, uif in [(fin, uin), (fout, uout)]:
334 if f is not uif:
335 os.dup2(f.fileno(), uif.fileno())
336 f.close()
337
338 class pipeservice(object): 309 class pipeservice(object):
339 def __init__(self, ui, repo, opts): 310 def __init__(self, ui, repo, opts):
340 self.ui = ui 311 self.ui = ui
341 self.repo = repo 312 self.repo = repo
342 313
345 316
346 def run(self): 317 def run(self):
347 ui = self.ui 318 ui = self.ui
348 # redirect stdio to null device so that broken extensions or in-process 319 # redirect stdio to null device so that broken extensions or in-process
349 # hooks will never cause corruption of channel protocol. 320 # hooks will never cause corruption of channel protocol.
350 fin, fout = _protectio(ui.fin, ui.fout) 321 fin, fout = procutil.protectstdio(ui.fin, ui.fout)
351 try: 322 try:
352 sv = server(ui, self.repo, fin, fout) 323 sv = server(ui, self.repo, fin, fout)
353 return sv.serve() 324 return sv.serve()
354 finally: 325 finally:
355 sv.cleanup() 326 sv.cleanup()
356 _restoreio(ui.fin, ui.fout, fin, fout) 327 procutil.restorestdio(ui.fin, ui.fout, fin, fout)
357 328
358 def _initworkerprocess(): 329 def _initworkerprocess():
359 # use a different process group from the master process, in order to: 330 # use a different process group from the master process, in order to:
360 # 1. make the current process group no longer "orphaned" (because the 331 # 1. make the current process group no longer "orphaned" (because the
361 # parent of this process is in a different process group while 332 # parent of this process is in a different process group while