1# Copyright 2015 The Chromium OS Authors. All rights reserved. 2# Use of this source code is governed by a BSD-style license that can be 3# found in the LICENSE file. 4 5import collections 6 7from autotest_lib.client.common_lib import error 8from autotest_lib.client.common_lib import process_utils 9from autotest_lib.client.common_lib import utils 10 11# Use this with ProcessWatcher to start your process in a minijail. This 12# is useful for instance if you would like to drop autotest's default root 13# priviledges. Both fields must be set to valid users/groups. 14MinijailConfig = collections.namedtuple('MinijailConfig', ['user', 'group']) 15 16 17class ProcessWatcher(object): 18 """Start a process, and terminate it later.""" 19 20 def __init__(self, command, args=tuple(), minijail_config=None, host=None): 21 """Construst a ProcessWatcher without starting the process. 22 23 @param command: string command to use to start the process. 24 @param args: list of strings to pass to the command. 25 @param minijail_config: MinijailConfig tuple defined above. 26 @param host: host object if the server should be started on a remote 27 host. 28 29 """ 30 self._command = ' '.join([command] + list(args)) 31 if '"' in self._command: 32 raise error.TestError('Please implement shell escaping in ' 33 'ProcessWatcher.') 34 self._minijail_config = minijail_config 35 self._run = utils.run if host is None else host.run 36 37 38 def start(self): 39 """Start a (potentially remote) instance of the process.""" 40 command = self._command 41 prefix = '' 42 if self._minijail_config is not None: 43 prefix = 'minijail0 -i -g %s -u %s ' % (self._minijail_config.group, 44 self._minijail_config.user) 45 # Redirect output streams to avoid odd interactions between autotest's 46 # shell environment and the command's runtime environment. 47 self._run('%s%s >/dev/null 2>&1 &' % (prefix, self._command)) 48 49 50 def close(self, timeout_seconds=40): 51 """Close the (potentially remote) instance of the process. 52 53 @param timeout_seconds: int number of seconds to wait for shutdown. 54 55 """ 56 process_utils.pkill_process(self._command, 57 timeout_seconds=timeout_seconds) 58