1# Copyright (c) 2013 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 os
6import re
7
8from autotest_lib.client.bin import test
9from autotest_lib.client.common_lib import error
10
11class platform_CheckCriticalProcesses(test.test):
12    """
13    Builds a process list (without spawning 'ps'), and validates
14    that among these processes all the expected processes are running.
15    """
16    version = 1
17
18    def get_process_name(self, pid):
19        """Gathers info about one process, given its PID
20
21        @param pid string representing the process ID
22        @return string process name
23
24        """
25        with open(os.path.join('/proc', pid, 'status')) as pid_status_file:
26            for line in pid_status_file:
27                fields = re.split('\s+',line)
28                if fields[0] == 'Name:':
29                    return fields[1]
30
31
32    def get_process_list(self):
33        """Returns the set the process names"""
34        process_names = set()
35        for pid in os.listdir('/proc'):
36            if not pid.isdigit():
37                continue
38
39            # There can be a race where after we listdir(), a process
40            # exits. In that case get_process_name will throw an IOError
41            # becase /proc/NNNN won't exist.
42            # In those cases, skip to the next go-round of our loop.
43            try:
44                process_names.add(self.get_process_name(pid))
45            except IOError:
46                continue
47
48        return process_names
49
50
51    def run_once(self, process_list):
52        """
53        Verify processes in |process_list| are running.
54
55        @param process_list: list of process names to check
56        """
57        processes = self.get_process_list()
58        missing_processes = []
59        for p in process_list:
60            processes_names = p.split('|')
61            if set(processes_names).isdisjoint(processes):
62                missing_processes.append(p)
63        if missing_processes:
64            raise error.TestFail('The following processes are not running: %r.'
65                                  % missing_processes)
66