Patchwork lib/oeqa/utils: sshcontrol: make timeout depend on output

login
register
mail settings
Submitter Stanacar, StefanX
Date Nov. 3, 2013, 12:27 p.m.
Message ID <1383481636-30346-1-git-send-email-stefanx.stanacar@intel.com>
Download mbox | patch
Permalink /patch/61035/
State Accepted
Commit 1e16634af63a49c3a59335e47d96691ff4df2a7a
Headers show

Comments

Stanacar, StefanX - Nov. 3, 2013, 12:27 p.m.
Instead of running the commands with a fixed timeout,
we should kill the command if there is no output
for timeout seconds.
Also changed some strings/comments.

Signed-off-by: Stefan Stanacar <stefanx.stanacar@intel.com>
---
 meta/lib/oeqa/utils/sshcontrol.py | 41 ++++++++++++++++++++++++++-------------
 1 file changed, 27 insertions(+), 14 deletions(-)

Patch

diff --git a/meta/lib/oeqa/utils/sshcontrol.py b/meta/lib/oeqa/utils/sshcontrol.py
index 1539ff2..07257b8 100644
--- a/meta/lib/oeqa/utils/sshcontrol.py
+++ b/meta/lib/oeqa/utils/sshcontrol.py
@@ -9,6 +9,7 @@ 
 import subprocess
 import time
 import os
+import select
 
 class SSHControl(object):
 
@@ -50,32 +51,44 @@  class SSHControl(object):
         if self.host:
             sshconn = self._internal_run(cmd)
         else:
-            raise Exception("Remote IP hasn't been set: '%s'" % actualcmd)
+            raise Exception("Remote IP/host hasn't been set, I can't run ssh without one.")
 
+        # run the command forever
         if timeout == 0:
-            self._out = sshconn.communicate()[0]
-            self._ret = sshconn.poll()
+            output = sshconn.communicate()[0]
         else:
+            # use the default timeout
             if timeout is None:
                 tdelta = self.timeout
+            # use the specified timeout
             else:
                 tdelta = timeout
             endtime = self._starttime + tdelta
-            while sshconn.poll() is None and time.time() < endtime:
-                time.sleep(1)
+            output = ''
+            eof = False
+            while time.time() < endtime and not eof:
+                if select.select([sshconn.stdout], [], [], 5)[0] != []:
+                    data = os.read(sshconn.stdout.fileno(), 1024)
+                    if not data:
+                        sshconn.stdout.close()
+                        eof = True
+                    else:
+                        output += data
+                        endtime = time.time() + tdelta
+
             # process hasn't returned yet
             if sshconn.poll() is None:
-                self._ret = 255
                 sshconn.terminate()
-                sshconn.kill()
-                self._out = sshconn.stdout.read()
-                sshconn.stdout.close()
-                self._out += "\n[!!! SSH command timed out after %d seconds and it was killed]" % tdelta
-            else:
-                self._out = sshconn.stdout.read()
-                self._ret = sshconn.poll()
+                time.sleep(3)
+                try:
+                    sshconn.kill()
+                except OSError:
+                    pass
+                output += "\n[!!! SSH command killed - no output for %d seconds. Total running time: %d seconds." % (tdelta, time.time() - self._starttime)
+
+        self._ret = sshconn.poll()
         # strip the last LF so we can test the output
-        self._out = self._out.rstrip()
+        self._out = output.rstrip()
         self.log("%s" % self._out)
         self.log("[SSH command returned after %d seconds]: %s" % (time.time() - self._starttime, self._ret))
         return (self._ret, self._out)