<html>
  <head>
    <meta content="text/html; charset=UTF-8" http-equiv="Content-Type">
  </head>
  <body text="#000000" bgcolor="#FFFFFF">
    <div class="moz-cite-prefix">On 2014年01月10日 21:34, Sheldon wrote:<br>
    </div>
    <blockquote cite="mid:52CFF6CF.9020709@linux.vnet.ibm.com"
      type="cite">
      <meta content="text/html; charset=UTF-8" http-equiv="Content-Type">
      <div class="moz-cite-prefix">How about just check timeout by 
        ”proc.returncode == -9“, not sure we can kill the subprocess
        manually. <br>
        <br>
        The follow is an Example:<br>
        <br>
        <i>import subprocess</i><i><br>
        </i><i>from threading import Timer</i><i><br>
        </i><i><br>
        </i><i>def run_command(cmd, timeout=None):</i><i><br>
        </i><i>    proc = None</i><i><br>
        </i><i>    timeout_flag = False</i><i><br>
        </i><i><br>
        </i><i>    try:</i><i><br>
        </i><i>        proc = subprocess.Popen(cmd,
          stdout=subprocess.PIPE,</i><i><br>
        </i><i>                                stderr=subprocess.PIPE)</i><i><br>
        </i><i>        if timeout is not None:</i><i><br>
        </i><i>            timer = Timer(timeout, lambda proc:
          proc.kill(), [proc])</i><i><br>
        </i><i>            timer.start()</i><i><br>
        </i><i><br>
        </i><i>        out, error = proc.communicate()</i><i><br>
        </i><i>        print "Run command '%s'" % " ".join(cmd)</i><i><br>
        </i><i><br>
        </i><i>        if out or error:</i><i><br>
        </i><i>            print "out:\n %s\nerror:\n %s" % (out, error)</i><i><br>
        </i><i>        if proc.returncode == -9:</i><i><br>
        </i><i>            timeout_flag = True</i><i><br>
        </i><i>            print "process is killed by signal.SIGKILL
          for timeout %s seconds" % timeout</i><i><br>
        </i><i>        if timeout is not None:</i><i><br>
        </i><i>            timer.cancel()</i><i><br>
        </i><i>        return out, error, proc.returncode, timeout_flag</i><i><br>
        </i><i>    except Exception as e:</i><i><br>
        </i><i>        msg = "Failed to run command: %s." % "
          ".join(cmd)</i><i><br>
        </i><i>        print "%s\n  %s" % (msg, e)</i><i><br>
        </i><i>        return None, None, None, timeout_flag</i><i><br>
        </i><i><br>
        </i><br>
        On 01/10/2014 04:16 PM, Royce Lv wrote:<br>
      </div>
      <blockquote cite="mid:52CFAC79.5060207@linux.vnet.ibm.com"
        type="cite">On 2014年01月10日 09:00, <a moz-do-not-send="true"
          class="moz-txt-link-abbreviated"
          href="mailto:shaohef@linux.vnet.ibm.com">shaohef@linux.vnet.ibm.com</a>
        wrote: <br>
        <blockquote type="cite">From: ShaoHe Feng <a
            moz-do-not-send="true" class="moz-txt-link-rfc2396E"
            href="mailto:shaohef@linux.vnet.ibm.com">&lt;shaohef@linux.vnet.ibm.com&gt;</a>
          <br>
          <br>
          We need a common function to execute shell command. <br>
          We also need timeout when execute shell command. <br>
          <br>
          A threading.Timer is used to send signal.SIGKILL to kill the
          command <br>
          when timeout. <br>
          <br>
          Signed-off-by: Royce Lv <a moz-do-not-send="true"
            class="moz-txt-link-rfc2396E"
            href="mailto:lvroyce@linux.vnet.ibm.com">&lt;lvroyce@linux.vnet.ibm.com&gt;</a>
          <br>
          Signed-off-by: ShaoHe Feng <a moz-do-not-send="true"
            class="moz-txt-link-rfc2396E"
            href="mailto:shaohef@linux.vnet.ibm.com">&lt;shaohef@linux.vnet.ibm.com&gt;</a>
          <br>
          --- <br>
            src/kimchi/utils.py | 39
          +++++++++++++++++++++++++++++++++++++++ <br>
            1 file changed, 39 insertions(+) <br>
          <br>
          diff --git a/src/kimchi/utils.py b/src/kimchi/utils.py <br>
          index af245c6..94097ad 100644 <br>
          --- a/src/kimchi/utils.py <br>
          +++ b/src/kimchi/utils.py <br>
          @@ -23,6 +23,7 @@ <br>
          <br>
            import cherrypy <br>
            import os <br>
          +import subprocess <br>
            import urllib2 <br>
          <br>
          <br>
          @@ -30,6 +31,7 @@ from cherrypy.lib.reprconf import Parser <br>
          <br>
          <br>
            from kimchi import config <br>
          +from threading import Timer <br>
          <br>
          <br>
            kimchi_log = cherrypy.log.error_log <br>
          @@ -96,3 +98,40 @@ def check_url_path(path): <br>
                    return False <br>
          <br>
                return True <br>
          + <br>
          + <br>
          +def run_command(cmd, timeout=None): <br>
          +    def kill_proc(proc, timeout_flag): <br>
          +        timeout_flag[0] = True <br>
          +        proc.kill() <br>
          + <br>
          +    proc = None <br>
          +    timer = None <br>
          +    timeout_flag = [False] <br>
          + <br>
          +    try: <br>
          +        proc = subprocess.Popen(cmd, stdout=subprocess.PIPE,
          <br>
          +                                stderr=subprocess.PIPE) <br>
          +        if timeout is not None: <br>
          +            timer = Timer(timeout, kill_proc, [proc,
          timeout_flag]) <br>
          +            timer.start() <br>
        </blockquote>
        I like the idea of using timer, I think the only thing we need
        to take care is check timeout happens and report a specific
        error. <br>
        Or when we kill the proc and it is blocked, the
        proc.communicate() error will not be 'timeout happens' <br>
        <blockquote type="cite">+ <br>
          +        out, error = proc.communicate() <br>
          +        kimchi_log.debug("Run command '%s'", " ".join(cmd)) <br>
          + <br>
          +        if out or error: <br>
          +            kimchi_log.debug("out:\n %s\nerror:\n %s", out,
          error) <br>
          + <br>
          +        return out, error, proc.returncode, timeout_flag[0] <br>
          +    except Exception as e: <br>
          +        msg = "Failed to run command: %s." % " ".join(cmd) <br>
          +        msg = msg if proc is None else msg + "\n  error code:
          %s." <br>
          +        kimchi_log.error("%s\n  %s", msg, e) <br>
          + <br>
          +        if proc: <br>
          +            return out, error, proc.returncode,
          timeout_flag[0] <br>
          +        else: <br>
          +            return None, None, None, timeout_flag[0] <br>
        </blockquote>
      </blockquote>
    </blockquote>
    I like the idea raise Timeout Exception better, because when timeout
    occurs, the ordinary execution of cmd becomes invalid and we do not
    need to check the execute result any more.<br>
    And outside of this helper function, I think using:<br>
    try:<br>
        run_cmd(cmd)<br>
    except TimeoutException:<br>
       ...<br>
    Will help to separate the ordinary logic. What do you think?<br>
    <blockquote cite="mid:52CFF6CF.9020709@linux.vnet.ibm.com"
      type="cite">
      <blockquote cite="mid:52CFAC79.5060207@linux.vnet.ibm.com"
        type="cite">
        <blockquote type="cite"> +    finally: <br>
          +        if timer and not timeout_flag[0]: <br>
          +            timer.cancel() <br>
        </blockquote>
        <br>
      </blockquote>
      <br>
      <br>
      <pre class="moz-signature" cols="72">-- 
Thanks and best regards!

Sheldon Feng(冯少合)<a moz-do-not-send="true" class="moz-txt-link-rfc2396E" href="mailto:shaohef@linux.vnet.ibm.com">&lt;shaohef@linux.vnet.ibm.com&gt;</a>
IBM Linux Technology Center</pre>
    </blockquote>
    <br>
  </body>
</html>