On 2014年01月10日 21:34, Sheldon wrote:
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]
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.
And outside of this helper function, I think using:
try:
run_cmd(cmd)
except TimeoutException:
...
Will help to separate the ordinary logic. What do you think?
>> + 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