1 // 2 // Copyright (C) 2011 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 UPDATE_ENGINE_COMMON_SUBPROCESS_H_ 18 #define UPDATE_ENGINE_COMMON_SUBPROCESS_H_ 19 20 #include <unistd.h> 21 22 #include <map> 23 #include <memory> 24 #include <string> 25 #include <vector> 26 27 #include <base/callback.h> 28 #include <base/files/file_descriptor_watcher_posix.h> 29 #include <base/logging.h> 30 #include <base/macros.h> 31 #include <brillo/asynchronous_signal_handler_interface.h> 32 #include <brillo/message_loops/message_loop.h> 33 #ifdef __CHROMEOS__ 34 #include <brillo/process/process.h> 35 #include <brillo/process/process_reaper.h> 36 #else 37 #include <brillo/process.h> 38 #include <brillo/process_reaper.h> 39 #endif // __CHROMEOS__ 40 #include <gtest/gtest_prod.h> 41 42 // The Subprocess class is a singleton. It's used to spawn off a subprocess 43 // and get notified when the subprocess exits. The result of Exec() can 44 // be saved and used to cancel the callback request and kill your process. If 45 // you know you won't call KillExec(), you may safely lose the return value 46 // from Exec(). 47 48 // To create the Subprocess singleton just instantiate it with and call Init(). 49 // You can't have two Subprocess instances initialized at the same time. 50 51 namespace chromeos_update_engine { 52 53 class Subprocess { 54 public: 55 enum Flags { 56 kSearchPath = 1 << 0, 57 kRedirectStderrToStdout = 1 << 1, 58 }; 59 60 // Callback type used when an async process terminates. It receives the exit 61 // code and the stdout output (and stderr if redirected). 62 using ExecCallback = base::Callback<void(int, const std::string&)>; 63 64 Subprocess() = default; 65 66 // Destroy and unregister the Subprocess singleton. 67 ~Subprocess(); 68 69 // Initialize and register the Subprocess singleton. 70 void Init(brillo::AsynchronousSignalHandlerInterface* async_signal_handler); 71 72 // Launches a process in the background and calls the passed |callback| when 73 // the process exits. The file descriptors specified in |output_pipes| will 74 // be available in the child as the writer end of a pipe. Use GetPipeFd() to 75 // know the reader end in the parent. Only stdin, stdout, stderr and the file 76 // descriptors in |output_pipes| will be open in the child. 77 // Returns the process id of the new launched process or 0 in case of failure. 78 pid_t Exec(const std::vector<std::string>& cmd, const ExecCallback& callback); 79 pid_t ExecFlags(const std::vector<std::string>& cmd, 80 uint32_t flags, 81 const std::vector<int>& output_pipes, 82 const ExecCallback& callback); 83 84 // Kills the running process with SIGTERM and ignores the callback. 85 void KillExec(pid_t pid); 86 87 // Return the parent end of the pipe mapped onto |fd| in the child |pid|. This 88 // file descriptor is available until the callback for the child |pid| 89 // returns. After that the file descriptor will be closed. The passed |fd| 90 // must be one of the file descriptors passed to ExecFlags() in 91 // |output_pipes|, otherwise returns -1. 92 int GetPipeFd(pid_t pid, int fd) const; 93 94 // Executes a command synchronously. Returns true on success. If |stdout_str| 95 // is non-null, the process output is stored in it, otherwise the output is 96 // logged. 97 static bool SynchronousExec(const std::vector<std::string>& cmd, 98 int* return_code, 99 std::string* stdout_str, 100 std::string* stderr_str); 101 static bool SynchronousExecFlags(const std::vector<std::string>& cmd, 102 uint32_t flags, 103 int* return_code, 104 std::string* stdout_str, 105 std::string* stderr_str); 106 107 // Gets the one instance. Get()108 static Subprocess& Get() { return *subprocess_singleton_; } 109 110 // Tries to log all in flight processes's output. It is used right before 111 // exiting the update_engine, probably when the subprocess caused a system 112 // shutdown. 113 void FlushBufferedLogsAtExit(); 114 115 private: 116 FRIEND_TEST(SubprocessTest, CancelTest); 117 118 struct SubprocessRecord { SubprocessRecordSubprocessRecord119 explicit SubprocessRecord(const ExecCallback& callback) 120 : callback(callback) {} 121 122 // The callback supplied by the caller. 123 ExecCallback callback; 124 125 // The ProcessImpl instance managing the child process. Destroying this 126 // will close our end of the pipes we have open. 127 brillo::ProcessImpl proc; 128 129 // These are used to monitor the stdout of the running process, including 130 // the stderr if it was redirected. 131 std::unique_ptr<base::FileDescriptorWatcher::Controller> stdout_controller; 132 133 int stdout_fd{-1}; 134 std::string stdout_str; 135 }; 136 137 // Callback which runs whenever there is input available on the subprocess 138 // stdout pipe. 139 static void OnStdoutReady(SubprocessRecord* record); 140 141 // Callback for when any subprocess terminates. This calls the user 142 // requested callback. 143 void ChildExitedCallback(const siginfo_t& info); 144 145 // The global instance. 146 static Subprocess* subprocess_singleton_; 147 148 // A map from the asynchronous subprocess tag (see Exec) to the subprocess 149 // record structure for all active asynchronous subprocesses. 150 std::map<pid_t, std::unique_ptr<SubprocessRecord>> subprocess_records_; 151 152 // Used to watch for child processes. 153 brillo::ProcessReaper process_reaper_; 154 155 DISALLOW_COPY_AND_ASSIGN(Subprocess); 156 }; 157 158 } // namespace chromeos_update_engine 159 160 #endif // UPDATE_ENGINE_COMMON_SUBPROCESS_H_ 161