# Copyright 2015 The Chromium OS Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. import collections from autotest_lib.client.common_lib import error from autotest_lib.client.common_lib import process_utils from autotest_lib.client.common_lib import utils # Use this with ProcessWatcher to start your process in a minijail. This # is useful for instance if you would like to drop autotest's default root # priviledges. Both fields must be set to valid users/groups. MinijailConfig = collections.namedtuple('MinijailConfig', ['user', 'group']) class ProcessWatcher(object): """Start a process, and terminate it later.""" def __init__(self, command, args=tuple(), minijail_config=None, host=None): """Construst a ProcessWatcher without starting the process. @param command: string command to use to start the process. @param args: list of strings to pass to the command. @param minijail_config: MinijailConfig tuple defined above. @param host: host object if the server should be started on a remote host. """ self._command = ' '.join([command] + list(args)) if '"' in self._command: raise error.TestError('Please implement shell escaping in ' 'ProcessWatcher.') self._minijail_config = minijail_config self._run = utils.run if host is None else host.run def start(self): """Start a (potentially remote) instance of the process.""" command = self._command prefix = '' if self._minijail_config is not None: prefix = 'minijail0 -i -g %s -u %s ' % (self._minijail_config.group, self._minijail_config.user) # Redirect output streams to avoid odd interactions between autotest's # shell environment and the command's runtime environment. self._run('%s%s >/dev/null 2>&1 &' % (prefix, self._command)) def close(self, timeout_seconds=40): """Close the (potentially remote) instance of the process. @param timeout_seconds: int number of seconds to wait for shutdown. """ process_utils.pkill_process(self._command, timeout_seconds=timeout_seconds)