1 // 2 // Copyright (C) 2015 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 17 #ifndef SHILL_PROCESS_MANAGER_H_ 18 #define SHILL_PROCESS_MANAGER_H_ 19 20 #include <map> 21 #include <string> 22 #include <vector> 23 24 #include <base/callback.h> 25 #include <base/cancelable_callback.h> 26 #include <base/files/file_path.h> 27 #include <base/lazy_instance.h> 28 #include <base/memory/weak_ptr.h> 29 #include <base/tracked_objects.h> 30 #include <brillo/minijail/minijail.h> 31 #include <brillo/process.h> 32 #include <brillo/process_reaper.h> 33 34 namespace shill { 35 36 class EventDispatcher; 37 38 // The ProcessManager is a singleton providing process creation and 39 // asynchronous process termination. Need to initialize it once with 40 // Init method call. 41 class ProcessManager { 42 public: 43 virtual ~ProcessManager(); 44 45 // This is a singleton -- use ProcessManager::GetInstance()->Foo(). 46 static ProcessManager* GetInstance(); 47 48 // Register async signal handler and setup process reaper. 49 virtual void Init(EventDispatcher* dispatcher); 50 51 // Call on shutdown to release async_signal_handler_. 52 virtual void Stop(); 53 54 // Create and start a process for |program| with |arguments|. |enivronment| 55 // variables will be setup in the child process before exec the |program|. 56 // |terminate_with_parent| is used to indicate if child process should 57 // self terminate if the parent process exits. |exit_callback| will be 58 // invoked when child process exits (not terminated by us). Return -1 59 // if failed to start the process, otherwise, return the pid of the child 60 // process. 61 virtual pid_t StartProcess( 62 const tracked_objects::Location& spawn_source, 63 const base::FilePath& program, 64 const std::vector<std::string>& arguments, 65 const std::map<std::string, std::string>& environment, 66 bool terminate_with_parent, 67 const base::Callback<void(int)>& exit_callback); 68 69 // Similar to StartProcess(), with the following differences: 70 // - environment variables are not supported (no need yet) 71 // - terminate_with_parent is not supported (may be non-trivial) 72 // - the child process will run as |user| and |group| 73 // - the |capmask| argument can be used to provide the child process 74 // with capabilities, which |user| might not have on its own StartProcessInMinijail(const tracked_objects::Location & spawn_source,const base::FilePath & program,const std::vector<std::string> & arguments,const std::string & user,const std::string & group,uint64_t capmask,const base::Callback<void (int)> & exit_callback)75 virtual pid_t StartProcessInMinijail( 76 const tracked_objects::Location& spawn_source, 77 const base::FilePath& program, 78 const std::vector<std::string>& arguments, 79 const std::string& user, 80 const std::string& group, 81 uint64_t capmask, 82 const base::Callback<void(int)>& exit_callback) { 83 return StartProcessInMinijailWithPipes( 84 spawn_source, program, arguments, user, group, capmask, exit_callback, 85 nullptr, nullptr, nullptr); 86 } 87 88 // Similar to StartProcessInMinijail(), with the additional ability to 89 // pipe the child's stdin/stdout/stderr back to us. If any of those 90 // streams is not needed, simply pass nullptr for the corresponding 91 // 'fd' argument. If no pipes are needed, use StartProcessInMinijail(). 92 virtual pid_t StartProcessInMinijailWithPipes( 93 const tracked_objects::Location& spawn_source, 94 const base::FilePath& program, 95 const std::vector<std::string>& arguments, 96 const std::string& user, 97 const std::string& group, 98 uint64_t capmask, 99 const base::Callback<void(int)>& exit_callback, 100 int* stdin_fd, 101 int* stdout_fd, 102 int* stderr_fd); 103 104 // Stop the given |pid|. Previously registered |exit_callback| will be 105 // unregistered, since the caller is not interested in this process anymore 106 // and that callback might not be valid by the time this process terminates. 107 // This will attempt to terminate the child process by sending a SIGTERM 108 // signal first. If the process doesn't terminate within a certain time, 109 // ProcessManager will attempt to send a SIGKILL signal. It will give up 110 // with an error log If the process still doesn't terminate within a certain 111 // time. 112 virtual bool StopProcess(pid_t pid); 113 114 // Stop the given |pid| in a synchronous manner. 115 virtual bool StopProcessAndBlock(pid_t pid); 116 117 // Replace the current exit callback for |pid| with |new_callback|. 118 virtual bool UpdateExitCallback( 119 pid_t pid, 120 const base::Callback<void(int)>& new_callback); 121 122 protected: 123 ProcessManager(); 124 125 private: 126 friend class ProcessManagerTest; 127 friend struct base::DefaultLazyInstanceTraits<ProcessManager>; 128 129 using TerminationTimeoutCallback = base::CancelableClosure; 130 131 // Invoked when process |pid| exited. 132 void OnProcessExited(pid_t pid, const siginfo_t& info); 133 134 // Invoked when process |pid| did not terminate within a certain timeout. 135 // |kill_signal| indicates the signal used for termination. When it is set 136 // to true, SIGKILL was used to terminate the process, otherwise, SIGTERM 137 // was used. 138 void ProcessTerminationTimeoutHandler(pid_t pid, bool kill_signal); 139 140 // Send a termination signal to process |pid|. If |kill_signal| is set to 141 // true, SIGKILL is sent, otherwise, SIGTERM is sent. After signal is sent, 142 // |pid| and timeout handler is added to |pending_termination_processes_| 143 // list, to make sure process |pid| does exit in timely manner. 144 bool TerminateProcess(pid_t pid, bool kill_signal); 145 146 // Kill process |pid|. If |kill_signal| is true it will send SIGKILL, 147 // otherwise it will send SIGTERM. 148 // It returns true when the process was already dead or killed within 149 // the timeout. 150 // It returns false when the process failed to exit within the timeout 151 // or the system failed to send kill singal. 152 bool KillProcessWithTimeout(pid_t pid, bool kill_signal); 153 154 // Kill process |pid| using signal |signal|. 155 // The |killed| will be set true when the process was already dead. 156 // It returns true when it sent the |signal| successfully or the 157 // process was already dead. 158 // It returns false when the system failed to send |signal|. 159 bool KillProcess(pid_t pid, int signal, bool* killed); 160 161 // Wait for process |pid| to exit. This function will check it for at most 162 // |tries| times. The interval of waiting time grows exponentially from 163 // |sleep_ms| and it has an |upper_bound_ms| upper bound. 164 bool WaitpidWithTimeout(pid_t pid, 165 unsigned int sleep_ms, 166 unsigned int upper_bound_ms, 167 int tries); 168 169 // Used to watch processes. 170 std::unique_ptr<brillo::AsynchronousSignalHandler> async_signal_handler_; 171 brillo::ProcessReaper process_reaper_; 172 173 EventDispatcher* dispatcher_; 174 brillo::Minijail* minijail_; 175 176 // Processes to watch for the caller. 177 std::map<pid_t, base::Callback<void(int)>> watched_processes_; 178 // Processes being terminated by us. Use a timer to make sure process 179 // does exit, log an error if it failed to exit within a specific timeout. 180 std::map<pid_t, std::unique_ptr<TerminationTimeoutCallback>> 181 pending_termination_processes_; 182 183 base::WeakPtrFactory<ProcessManager> weak_factory_{this}; 184 DISALLOW_COPY_AND_ASSIGN(ProcessManager); 185 }; 186 187 } // namespace shill 188 189 #endif // SHILL_PROCESS_MANAGER_H_ 190