1
0
mirror of https://github.com/ARM-software/devlib.git synced 2025-01-31 02:00:45 +00:00

target: Fix and generalize Target.kick_off()

kick_off() implementation had a number of issue:
* Target specific implementation making testing more difficult.
* Not wrapping the command in sh -c lead to blocking behavior if the
  command had multiple parts, e.g. "sleep 42; echo foo"
* nohup sometimes writes to stdout, breaking return code parsing in
  adb_shell().

These issues are fixed by a generic implementing of kick_off() that
simply delegates to Target.background().

Fixes https://github.com/ARM-software/devlib/issues/623
This commit is contained in:
Douglas Raillard 2023-04-04 10:40:34 +01:00 committed by Marc Bonnici
parent 9e0300b9f2
commit 27fb0453a3

View File

@ -974,8 +974,19 @@ class Target(object):
command = 'cd {} && {}'.format(quote(in_directory), command) command = 'cd {} && {}'.format(quote(in_directory), command)
return self.background(command, as_root=as_root) return self.background(command, as_root=as_root)
def kick_off(self, command, as_root=False): @asyn.asyncf
raise NotImplementedError() async def kick_off(self, command, as_root=None):
"""
Like execute() but returns immediately. Unlike background(), it will
not return any handle to the command being run.
"""
cmd = 'cd {wd} && {busybox} sh -c {cmd} >/dev/null 2>&1'.format(
wd=quote(self.working_directory),
busybox=quote(self.busybox),
cmd=quote(command)
)
self.background(cmd, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, as_root=as_root)
# sysfs interaction # sysfs interaction
@ -1581,11 +1592,6 @@ class LinuxTarget(Target):
def wait_boot_complete(self, timeout=10): def wait_boot_complete(self, timeout=10):
pass pass
@call_conn
def kick_off(self, command, as_root=False):
command = 'sh -c {} 1>/dev/null 2>/dev/null &'.format(quote(command))
return self.conn.execute(command, as_root=as_root)
@asyn.asyncf @asyn.asyncf
async def get_pids_of(self, process_name): async def get_pids_of(self, process_name):
"""Returns a list of PIDs of all processes with the specified name.""" """Returns a list of PIDs of all processes with the specified name."""
@ -1833,21 +1839,6 @@ class AndroidTarget(Target):
max_async=max_async, max_async=max_async,
) )
@asyn.asyncf
async def kick_off(self, command, as_root=None):
"""
Like execute but closes adb session and returns immediately, leaving the command running on the
device (this is different from execute(background=True) which keeps adb connection open and returns
a subprocess object).
"""
if as_root is None:
as_root = self.needs_su
try:
command = 'cd {} && {} nohup {} &'.format(quote(self.working_directory), quote(self.busybox), command)
await self.execute.asyn(command, timeout=1, as_root=as_root)
except TimeoutError:
pass
@asyn.asyncf @asyn.asyncf
async def __setup_list_directory(self): async def __setup_list_directory(self):
# In at least Linaro Android 16.09 (which was their first Android 7 release) and maybe # In at least Linaro Android 16.09 (which was their first Android 7 release) and maybe