Bug 782749 - add timeouts for shell/checkCmd to devicemanagerADB, r=jmaher

This commit is contained in:
Malini Das 2012-08-15 10:35:21 -04:00
Родитель 1e2f20e917
Коммит f158ad377a
3 изменённых файлов: 40 добавлений и 9 удалений

Просмотреть файл

@ -38,9 +38,12 @@ def abstractmethod(method):
class DeviceManager:
@abstractmethod
def shell(self, cmd, outputfile, env=None, cwd=None):
def shell(self, cmd, outputfile, env=None, cwd=None, timeout=None):
"""
executes shell command on device
timeout is specified in seconds, and if no timeout is given,
we will run until the script returns
returns:
success: Return code from command
failure: None

Просмотреть файл

@ -90,11 +90,13 @@ class DeviceManagerADB(DeviceManager):
if self.host:
self.disconnectRemoteADB()
# external function: executes shell command on device
# external function: executes shell command on device.
# timeout is specified in seconds, and if no timeout is given,
# we will run until the script returns
# returns:
# success: <return code>
# failure: None
def shell(self, cmd, outputfile, env=None, cwd=None):
def shell(self, cmd, outputfile, env=None, cwd=None, timeout=None):
# FIXME: this function buffers all output of the command into memory,
# always. :(
@ -117,6 +119,16 @@ class DeviceManagerADB(DeviceManager):
args.extend(["shell", cmdline])
proc = subprocess.Popen(args,
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
if timeout:
timeout = int(timeout)
start_time = time.time()
ret_code = proc.poll()
while ((time.time() - start_time) <= timeout) and ret_code == None:
time.sleep(1)
ret_code = proc.poll()
if ret_code == None:
proc.kill()
raise DMError("Timeout exceeded for shell call")
(stdout, stderr) = proc.communicate()
outputfile.write(stdout.rstrip('\n'))
@ -712,7 +724,9 @@ class DeviceManagerADB(DeviceManager):
args.insert(2, self.packageName)
return self.runCmd(args)
def checkCmd(self, args):
# timeout is specified in seconds, and if no timeout is given,
# we will run until the script returns
def checkCmd(self, args, timeout=None):
# If we are not root but have run-as, and we're trying to execute
# a shell command then using run-as is the best we can do
finalArgs = [self.adbPath]
@ -722,13 +736,25 @@ class DeviceManagerADB(DeviceManager):
args.insert(1, "run-as")
args.insert(2, self.packageName)
finalArgs.extend(args)
if timeout:
timeout = int(timeout)
proc = subprocess.Popen(finalArgs)
start_time = time.time()
ret_code = proc.poll()
while ((time.time() - start_time) <= timeout) and ret_code == None:
time.sleep(1)
ret_code = proc.poll()
if ret_code == None:
proc.kill()
raise DMError("Timeout exceeded for checkCmd call")
return ret_code
return subprocess.check_call(finalArgs)
def checkCmdAs(self, args):
def checkCmdAs(self, args, timeout=None):
if (self.useRunAs):
args.insert(1, "run-as")
args.insert(2, self.packageName)
return self.checkCmd(args)
return self.checkCmd(args, timeout)
# external function
# returns:

Просмотреть файл

@ -123,6 +123,8 @@ class DeviceManagerSUT(DeviceManager):
one fails. this is necessary in particular for pushFile(), where we don't want
to accidentally send extra data if a failure occurs during data transmission.
'''
if timeout:
raise NotImplementedError("'timeout' parameter is not yet supported")
while self.retries < self.retrylimit:
try:
self._doCmds(cmdlist, outputfile, timeout)
@ -261,16 +263,16 @@ class DeviceManagerSUT(DeviceManager):
# returns:
# success: <return code>
# failure: None
def shell(self, cmd, outputfile, env=None, cwd=None):
def shell(self, cmd, outputfile, env=None, cwd=None, timeout=None):
cmdline = self._escapedCommandLine(cmd)
if env:
cmdline = '%s %s' % (self.formatEnvString(env), cmdline)
try:
if cwd:
self.sendCmds([{ 'cmd': 'execcwd %s %s' % (cwd, cmdline) }], outputfile)
self.sendCmds([{ 'cmd': 'execcwd %s %s' % (cwd, cmdline) }], outputfile, timeout)
else:
self.sendCmds([{ 'cmd': 'exec su -c "%s"' % cmdline }], outputfile)
self.sendCmds([{ 'cmd': 'exec su -c "%s"' % cmdline }], outputfile, timeout)
except AgentError:
return None