Show More
@@ -7,7 +7,7 b'' | |||
|
7 | 7 | |
|
8 | 8 | from i18n import _ |
|
9 | 9 | import struct |
|
10 | import os, errno, traceback, SocketServer | |
|
10 | import sys, os, errno, traceback, SocketServer | |
|
11 | 11 | import dispatch, encoding, util |
|
12 | 12 | |
|
13 | 13 | logfile = None |
@@ -248,6 +248,29 b' class server(object):' | |||
|
248 | 248 | |
|
249 | 249 | return 0 |
|
250 | 250 | |
|
251 | def _protectio(ui): | |
|
252 | """ duplicates streams and redirect original to null if ui uses stdio """ | |
|
253 | ui.flush() | |
|
254 | newfiles = [] | |
|
255 | nullfd = os.open(os.devnull, os.O_RDWR) | |
|
256 | for f, sysf, mode in [(ui.fin, sys.stdin, 'rb'), | |
|
257 | (ui.fout, sys.stdout, 'wb')]: | |
|
258 | if f is sysf: | |
|
259 | newfd = os.dup(f.fileno()) | |
|
260 | os.dup2(nullfd, f.fileno()) | |
|
261 | f = os.fdopen(newfd, mode) | |
|
262 | newfiles.append(f) | |
|
263 | os.close(nullfd) | |
|
264 | return tuple(newfiles) | |
|
265 | ||
|
266 | def _restoreio(ui, fin, fout): | |
|
267 | """ restores streams from duplicated ones """ | |
|
268 | ui.flush() | |
|
269 | for f, uif in [(fin, ui.fin), (fout, ui.fout)]: | |
|
270 | if f is not uif: | |
|
271 | os.dup2(f.fileno(), uif.fileno()) | |
|
272 | f.close() | |
|
273 | ||
|
251 | 274 | class pipeservice(object): |
|
252 | 275 | def __init__(self, ui, repo, opts): |
|
253 | 276 | self.ui = ui |
@@ -258,8 +281,14 b' class pipeservice(object):' | |||
|
258 | 281 | |
|
259 | 282 | def run(self): |
|
260 | 283 | ui = self.ui |
|
261 | sv = server(ui, self.repo, ui.fin, ui.fout) | |
|
262 | return sv.serve() | |
|
284 | # redirect stdio to null device so that broken extensions or in-process | |
|
285 | # hooks will never cause corruption of channel protocol. | |
|
286 | fin, fout = _protectio(ui) | |
|
287 | try: | |
|
288 | sv = server(ui, self.repo, fin, fout) | |
|
289 | return sv.serve() | |
|
290 | finally: | |
|
291 | _restoreio(ui, fin, fout) | |
|
263 | 292 | |
|
264 | 293 | class _requesthandler(SocketServer.StreamRequestHandler): |
|
265 | 294 | def handle(self): |
@@ -492,6 +492,7 b' check that local configs for the cached ' | |||
|
492 | 492 | foo |
|
493 | 493 | |
|
494 | 494 | $ cat <<EOF > dbgui.py |
|
495 | > import os, sys | |
|
495 | 496 | > from mercurial import cmdutil, commands |
|
496 | 497 | > cmdtable = {} |
|
497 | 498 | > command = cmdutil.command(cmdtable) |
@@ -501,6 +502,14 b' check that local configs for the cached ' | |||
|
501 | 502 | > @command("debugprompt", norepo=True) |
|
502 | 503 | > def debugprompt(ui): |
|
503 | 504 | > ui.write("%s\\n" % ui.prompt("prompt:")) |
|
505 | > @command("debugreadstdin", norepo=True) | |
|
506 | > def debugreadstdin(ui): | |
|
507 | > ui.write("read: %r\n" % sys.stdin.read(1)) | |
|
508 | > @command("debugwritestdout", norepo=True) | |
|
509 | > def debugwritestdout(ui): | |
|
510 | > os.write(1, "low-level stdout fd and\n") | |
|
511 | > sys.stdout.write("stdout should be redirected to /dev/null\n") | |
|
512 | > sys.stdout.flush() | |
|
504 | 513 | > EOF |
|
505 | 514 | $ cat <<EOF >> .hg/hgrc |
|
506 | 515 | > [extensions] |
@@ -518,10 +527,15 b' check that local configs for the cached ' | |||
|
518 | 527 | ... runcommand(server, ['debugprompt', '--config', |
|
519 | 528 | ... 'ui.interactive=True'], |
|
520 | 529 | ... input=cStringIO.StringIO('5678\n')) |
|
530 | ... runcommand(server, ['debugreadstdin']) | |
|
531 | ... runcommand(server, ['debugwritestdout']) | |
|
521 | 532 | *** runcommand debuggetpass --config ui.interactive=True |
|
522 | 533 | password: 1234 |
|
523 | 534 | *** runcommand debugprompt --config ui.interactive=True |
|
524 | 535 | prompt: 5678 |
|
536 | *** runcommand debugreadstdin | |
|
537 | read: '' | |
|
538 | *** runcommand debugwritestdout | |
|
525 | 539 | |
|
526 | 540 | |
|
527 | 541 | run commandserver in commandserver, which is silly but should work: |
General Comments 0
You need to be logged in to leave comments.
Login now