How about just check timeout by ”proc.returncode == -9“, not sure we can
kill the subprocess manually.
The follow is an Example:
/import subprocess//
//from threading import Timer//
//
//def run_command(cmd, timeout=None)://
// proc = None//
// timeout_flag = False//
//
// try://
// proc = subprocess.Popen(cmd, stdout=subprocess.PIPE,//
// stderr=subprocess.PIPE)//
// if timeout is not None://
// timer = Timer(timeout, lambda proc: proc.kill(), [proc])//
// timer.start()//
//
// out, error = proc.communicate()//
// print "Run command '%s'" % " ".join(cmd)//
//
// if out or error://
// print "out:\n %s\nerror:\n %s" % (out, error)//
// if proc.returncode == -9://
// timeout_flag = True//
// print "process is killed by signal.SIGKILL for timeout %s
seconds" % timeout//
// if timeout is not None://
// timer.cancel()//
// return out, error, proc.returncode, timeout_flag//
// except Exception as e://
// msg = "Failed to run command: %s." % " ".join(cmd)//
// print "%s\n %s" % (msg, e)//
// return None, None, None, timeout_flag//
//
/
On 01/10/2014 04:16 PM, Royce Lv wrote:
On 2014年01月10日 09:00, shaohef(a)linux.vnet.ibm.com wrote:
> From: ShaoHe Feng <shaohef(a)linux.vnet.ibm.com>
>
> We need a common function to execute shell command.
> We also need timeout when execute shell command.
>
> A threading.Timer is used to send signal.SIGKILL to kill the command
> when timeout.
>
> Signed-off-by: Royce Lv <lvroyce(a)linux.vnet.ibm.com>
> Signed-off-by: ShaoHe Feng <shaohef(a)linux.vnet.ibm.com>
> ---
> src/kimchi/utils.py | 39 +++++++++++++++++++++++++++++++++++++++
> 1 file changed, 39 insertions(+)
>
> diff --git a/src/kimchi/utils.py b/src/kimchi/utils.py
> index af245c6..94097ad 100644
> --- a/src/kimchi/utils.py
> +++ b/src/kimchi/utils.py
> @@ -23,6 +23,7 @@
>
> import cherrypy
> import os
> +import subprocess
> import urllib2
>
>
> @@ -30,6 +31,7 @@ from cherrypy.lib.reprconf import Parser
>
>
> from kimchi import config
> +from threading import Timer
>
>
> kimchi_log = cherrypy.log.error_log
> @@ -96,3 +98,40 @@ def check_url_path(path):
> return False
>
> return True
> +
> +
> +def run_command(cmd, timeout=None):
> + def kill_proc(proc, timeout_flag):
> + timeout_flag[0] = True
> + proc.kill()
> +
> + proc = None
> + timer = None
> + timeout_flag = [False]
> +
> + try:
> + proc = subprocess.Popen(cmd, stdout=subprocess.PIPE,
> + stderr=subprocess.PIPE)
> + if timeout is not None:
> + timer = Timer(timeout, kill_proc, [proc, timeout_flag])
> + timer.start()
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.
Or when we kill the proc and it is blocked, the proc.communicate()
error will not be 'timeout happens'
> +
> + out, error = proc.communicate()
> + kimchi_log.debug("Run command '%s'", "
".join(cmd))
> +
> + if out or error:
> + kimchi_log.debug("out:\n %s\nerror:\n %s", out, error)
> +
> + return out, error, proc.returncode, timeout_flag[0]
> + except Exception as e:
> + msg = "Failed to run command: %s." % " ".join(cmd)
> + msg = msg if proc is None else msg + "\n error code: %s."
> + kimchi_log.error("%s\n %s", msg, e)
> +
> + if proc:
> + return out, error, proc.returncode, timeout_flag[0]
> + else:
> + return None, None, None, timeout_flag[0]
> + finally:
> + if timer and not timeout_flag[0]:
> + timer.cancel()
--
Thanks and best regards!
Sheldon Feng(冯少合)<shaohef(a)linux.vnet.ibm.com>
IBM Linux Technology Center