Mercurial > public > mercurial-scm > hg-stable
comparison mercurial/commandserver.py @ 37126: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
37125:4f742c2cb837 | 37126: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 |