From 24539c379756c5591df382058bbebb840809fbf6 Mon Sep 17 00:00:00 2001 From: hpk Date: Fri, 2 Feb 2007 02:44:31 +0100 Subject: [PATCH] [svn r37790] fix Ssh remote sanitzing of FD 1 and 0 and factor out the code in a function --HG-- branch : trunk --- py/execnet/register.py | 70 ++++++++++++++++++------------ py/execnet/testing/test_gateway.py | 19 ++++++-- 2 files changed, 58 insertions(+), 31 deletions(-) diff --git a/py/execnet/register.py b/py/execnet/register.py index e35cfcd12..040d72e6e 100644 --- a/py/execnet/register.py +++ b/py/execnet/register.py @@ -97,33 +97,8 @@ class PopenGateway(PopenCmdGateway): s = "\n".join([extra, "import sys ; sys.path[:0] = %r" % (plist,), "import os ; os.environ['PYTHONPATH'] = %r" % ppath, - # redirect file descriptors 0 and 1 to /dev/null, to avoid - # complete confusion (this is independent from the sys.stdout - # and sys.stderr redirection that gateway.remote_exec() can do) - # note that we redirect fd 2 on win too, since for some reason that - # blocks there, while it works (sending to stderr if possible else - # ignoring) on *nix - str(py.code.Source(""" - try: - devnull = os.devnull - except AttributeError: - if os.name == 'nt': - devnull = 'NUL' - else: - devnull = '/dev/null' - sys.stdin = os.fdopen(os.dup(0), 'rb', 0) - sys.stdout = os.fdopen(os.dup(1), 'wb', 0) - if os.name == 'nt': - sys.stderr = os.fdopen(os.dup(2), 'wb', 0) - fd = os.open(devnull, os.O_RDONLY) - os.dup2(fd, 0) - os.close(fd) - fd = os.open(devnull, os.O_WRONLY) - os.dup2(fd, 1) - if os.name == 'nt': - os.dup2(fd, 2) - os.close(fd) - """)), + str(py.code.Source(stdouterrin_setnull)), + "stdouterrin_setnull()", "" ]) super(PopenGateway, self)._remote_bootstrap_gateway(io, s) @@ -176,6 +151,46 @@ class SshGateway(PopenCmdGateway): cmd += ' -i %s' % (identity,) cmdline.insert(0, cmd) super(SshGateway, self).__init__(' '.join(cmdline)) + + def _remote_bootstrap_gateway(self, io, s=""): + extra = "\n".join([ + str(py.code.Source(stdouterrin_setnull)), + "stdouterrin_setnull()", + s, + ]) + super(SshGateway, self)._remote_bootstrap_gateway(io, extra) + +def stdouterrin_setnull(): + # redirect file descriptors 0 and 1 to /dev/null, to avoid + # complete confusion (this is independent from the sys.stdout + # and sys.stderr redirection that gateway.remote_exec() can do) + # note that we redirect fd 2 on win too, since for some reason that + # blocks there, while it works (sending to stderr if possible else + # ignoring) on *nix + import sys, os + try: + devnull = os.devnull + except AttributeError: + if os.name == 'nt': + devnull = 'NUL' + else: + devnull = '/dev/null' + sys.stdin = os.fdopen(os.dup(0), 'rb', 0) + sys.stdout = os.fdopen(os.dup(1), 'wb', 0) + if os.name == 'nt': + sys.stderr = os.fdopen(os.dup(2), 'wb', 0) + fd = os.open(devnull, os.O_RDONLY) + os.dup2(fd, 0) + os.close(fd) + fd = os.open(devnull, os.O_WRONLY) + os.dup2(fd, 1) + if os.name == 'nt': + os.dup2(fd, 2) + os.close(fd) + +# XXX +# XXX unusued code below +# XXX class ExecGateway(PopenGateway): def remote_exec_sync_stdcapture(self, lines, callback): @@ -224,3 +239,4 @@ class ExecGateway(PopenGateway): callback = self.callbacks[answerid] del self.callbacks[answerid] callback(value) + diff --git a/py/execnet/testing/test_gateway.py b/py/execnet/testing/test_gateway.py index 0b684193e..6ef7a719e 100644 --- a/py/execnet/testing/test_gateway.py +++ b/py/execnet/testing/test_gateway.py @@ -25,6 +25,20 @@ def test_getsource_no_colision(): (name, dottedname, olddottedname)) seen[name] = (dottedname, value) +def test_stdouterrin_setnull(): + cap = py.io.StdCaptureFD() + from py.__.execnet.register import stdouterrin_setnull + stdouterrin_setnull() + import os + os.write(1, "hello") + if os.name == "nt": + os.write(2, "world") + os.read(0, 1) + out, err = cap.reset() + assert not out + assert not err + + class TestMessage: def test_wire_protocol(self): for cls in gateway.Message._types.values(): @@ -177,12 +191,12 @@ class BasicRemoteExecution: # check that the both sides previous channels are really gone channel.waitclose(0.3) - assert channel.id not in self.gw._channelfactory._channels #assert c.id not in self.gw._channelfactory newchan = self.gw.remote_exec(''' assert %d not in channel.gateway._channelfactory._channels ''' % (channel.id)) newchan.waitclose(0.3) + assert channel.id not in self.gw._channelfactory._channels def test_channel_receiver_callback(self): l = [] @@ -454,9 +468,6 @@ class TestSshGateway(BasicRemoteExecution): py.test.skip("no known ssh target, use -S to set one") cls.gw = py.execnet.SshGateway(option.sshtarget) - def test_confusion_from_os_write_stdout(self): - py.test.skip("writing to FD 1 with SshGateways not supported yet") - def test_sshaddress(self): assert self.gw.remoteaddress == option.sshtarget