Commit ecfd53c1 authored by Wez's avatar Wez Committed by Commit Bot

[fuchsia] Fix RunPackage() to keep 'pm serve' live while running.

Fuchsia packages are cached rather than installed into a device's
package filesystem, and when resolving packages the system is at liberty
to return a cached package that may be older than the version that had
previously been run, if the package server is unavailable.

Ensure that the package server remains running for the duration of
RunPackage(), to ensure that the expected version is run.

Bug: 956100, fuchsia:49180
Change-Id: I4aeacbf451f5c2bde84e16b3ea35461d2b88fa4b
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2127368
Commit-Queue: Wez <wez@chromium.org>
Auto-Submit: Wez <wez@chromium.org>
Reviewed-by: default avatarKevin Marshall <kmarshall@chromium.org>
Cr-Commit-Position: refs/heads/master@{#754690}
parent f3f8d5dd
......@@ -41,6 +41,7 @@ class ManagedAmberRepo(AmberRepo):
def __init__(self, target):
AmberRepo.__init__(self, target)
self._with_count = 0
self._amber_root = tempfile.mkdtemp()
pm_tool = common.GetHostToolPathFromPlatform('pm')
......@@ -71,18 +72,23 @@ class ManagedAmberRepo(AmberRepo):
self._RegisterAmberRepository(self._amber_root, remote_port)
def __enter__(self):
self._with_count += 1
return self
def __exit__(self, type, value, tb):
"""Allows the repository to delete itself when it leaves the scope of a
'with' block."""
if self._amber_root:
self._with_count -= 1
if self._with_count > 0:
return
logging.info('Cleaning up Amber root: ' + self._amber_root)
shutil.rmtree(self._amber_root)
self._amber_root = None
self._UnregisterAmberRepository()
if self._pm_serve_task:
self._pm_serve_task.kill()
self._pm_serve_task = None
def GetPath(self):
return self._amber_root
......@@ -94,7 +100,7 @@ class ManagedAmberRepo(AmberRepo):
|remote_port|: The reverse-forwarded port used to connect to instance of
`pm serve` that is serving the contents of |tuf_repo|."""
# Extract the public signing key for inclusion in the config file.
# Extract the public signing key for inclusion in the config file.
root_keys = []
root_json_path = os.path.join(tuf_repo, 'repository', 'root.json')
root_json = json.load(open(root_json_path, 'r'))
......@@ -153,7 +159,8 @@ class ExternalAmberRepo(AmberRepo):
self._amber_root = amber_root
logging.info('Using existing Amber root: {}'.format(amber_root))
#TODO(kmarshall) : Find a way to programatically check if "fx serve" is running.
# TODO(kmarshall): Find a way to programmatically check if "fx serve" is
# running.
logging.info('Ensure that "fx serve" is running.')
def GetPath(self):
......
......@@ -217,7 +217,7 @@ class DeviceTarget(target.Target):
assert self._host
def _GetAmberRepo(self):
def GetAmberRepo(self):
if not self._amber_repo:
if self._fuchsia_out_dir:
# Deploy to an already-booted device running a local Fuchsia build.
......
......@@ -75,7 +75,7 @@ class EmuTarget(target.Target):
open(temporary_system_log_file.name, 'r').read())
raise
def _GetAmberRepo(self):
def GetAmberRepo(self):
if not self._amber_repo:
self._amber_repo = amber_repo.ManagedAmberRepo(self)
......
......@@ -161,13 +161,15 @@ def RunPackage(output_dir, target, package_paths, package_name,
system_logger = (
_AttachKernelLogReader(target) if args.system_logging else None)
try:
with target.GetAmberRepo():
if system_logger:
# Spin up a thread to asynchronously dump the system log to stdout
# for easier diagnoses of early, pre-execution failures.
log_output_quit_event = multiprocessing.Event()
log_output_thread = threading.Thread(
target=lambda: _DrainStreamToStdout(system_logger.stdout,
log_output_quit_event))
target=
lambda: _DrainStreamToStdout(system_logger.stdout, log_output_quit_event)
)
log_output_thread.daemon = True
log_output_thread.start()
......@@ -179,14 +181,15 @@ def RunPackage(output_dir, target, package_paths, package_name,
logging.info('Running application.')
command = ['run', _GetComponentUri(package_name)] + package_args
process = target.RunCommandPiped(command,
process = target.RunCommandPiped(
command,
stdin=open(os.devnull, 'r'),
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT)
if system_logger:
output_stream = MergedInputStream([process.stdout,
system_logger.stdout]).Start()
output_stream = MergedInputStream(
[process.stdout, system_logger.stdout]).Start()
else:
output_stream = process.stdout
......@@ -206,8 +209,8 @@ def RunPackage(output_dir, target, package_paths, package_name,
else:
# The test runner returns an error status code if *any* tests fail,
# so we should proceed anyway.
logging.warning('Process exited with status code %d.' %
process.returncode)
logging.warning(
'Process exited with status code %d.' % process.returncode)
finally:
if system_logger:
......
......@@ -236,8 +236,12 @@ class Target(object):
return 'x86_64'
raise Exception('Unknown target_cpu %s:' % self._target_cpu)
def _GetAmberRepo(self):
"""Returns an AmberRepo instance which serves packages for this Target."""
def GetAmberRepo(self):
"""Returns an AmberRepo instance which serves packages for this Target.
Callers should typically call GetAmberRepo() in a |with| statement, and
install and execute commands inside the |with| block, so that the returned
AmberRepo can teardown correctly, if necessary.
"""
pass
def InstallPackage(self, package_paths):
......@@ -246,7 +250,7 @@ class Target(object):
package_paths: Paths to the .far files to install."""
with self._GetAmberRepo() as amber_repo:
with self.GetAmberRepo() as amber_repo:
# Publish all packages to the serving TUF repository under |tuf_root|.
for next_package_path in package_paths:
amber_repo.PublishPackage(next_package_path)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment