1 /*
2  * Copyright (C) 2018 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 #pragma once
17 
18 #include <atomic>
19 #include <memory>
20 #include <mutex>
21 #include <set>
22 #include <string>
23 #include <thread>
24 #include <utility>
25 #include <vector>
26 
27 #include "common/libs/utils/result.h"
28 #include "common/libs/utils/subprocess.h"
29 #include "host/libs/config/command_source.h"
30 
31 namespace cuttlefish {
32 
33 struct MonitorEntry {
34   std::unique_ptr<Command> cmd;
35   bool can_sandbox;
36   std::unique_ptr<Subprocess> proc;
37   bool is_critical;
38 
MonitorEntryMonitorEntry39   MonitorEntry(Command command, bool is_critical)
40       : cmd(new Command(std::move(command))), is_critical(is_critical) {}
41 };
42 
43 // Launches and keeps track of subprocesses, decides response if they
44 // unexpectedly exit
45 class ProcessMonitor {
46  public:
47   class Properties {
48    public:
49     Properties& RestartSubprocesses(bool) &;
50     Properties RestartSubprocesses(bool) &&;
51 
52     Properties& AddCommand(MonitorCommand) &;
53     Properties AddCommand(MonitorCommand) &&;
54 
55     Properties& StraceCommands(std::set<std::string>) &;
56     Properties StraceCommands(std::set<std::string>) &&;
57 
58     Properties& StraceLogDir(std::string) &;
59     Properties StraceLogDir(std::string) &&;
60 
61     Properties& SandboxProcesses(bool) &;
62     Properties SandboxProcesses(bool) &&;
63 
64     template <typename T>
AddCommands(T commands)65     Properties& AddCommands(T commands) & {
66       for (auto& command : commands) {
67         AddCommand(std::move(command));
68       }
69       return *this;
70     }
71 
72     template <typename T>
AddCommands(T commands)73     Properties AddCommands(T commands) && {
74       return std::move(AddCommands(std::move(commands)));
75     }
76 
77    private:
78     bool restart_subprocesses_;
79     std::vector<MonitorEntry> entries_;
80     std::set<std::string> strace_commands_;
81     std::string strace_log_dir_;
82     bool sandbox_processes_;
83 
84     friend class ProcessMonitor;
85   };
86   /*
87    * secure_env_fd is to send suspend/resume commands to secure_env.
88    */
89   ProcessMonitor(Properties&&, const SharedFD& secure_env_fd);
90 
91   // Start all processes given by AddCommand.
92   Result<void> StartAndMonitorProcesses();
93   // Stops all monitored subprocesses.
94   Result<void> StopMonitoredProcesses();
95   // Suspend all host subprocesses
96   Result<void> SuspendMonitoredProcesses();
97   // Resume all host subprocesses
98   Result<void> ResumeMonitoredProcesses();
99 
100  private:
101   Result<void> StartSubprocesses(Properties& properties);
102   Result<void> MonitorRoutine();
103   Result<void> ReadMonitorSocketLoop(std::atomic_bool&);
104   /*
105    * The child run_cvd process suspends the host processes
106    */
107   Result<void> SuspendHostProcessesImpl();
108   /*
109    * The child run_cvd process resumes the host processes
110    */
111   Result<void> ResumeHostProcessesImpl();
112 
113   Properties properties_;
114   const SharedFD channel_to_secure_env_;
115   pid_t monitor_;
116   SharedFD parent_monitor_socket_;
117   SharedFD child_monitor_socket_;
118 
119   /*
120    * The lock that should be acquired when multiple threads
121    * access to properties_. Currently, used by the child
122    * run_cvd process that runs MonitorRoutine()
123    */
124   std::mutex properties_mutex_;
125 };
126 
127 }  // namespace cuttlefish
128