1 // Copyright (C) 2022 The Android Open Source Project 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 #pragma once 15 16 #include <atomic> 17 #include <chrono> 18 #include <condition_variable> 19 #include <cstdio> 20 #include <functional> 21 #include <future> 22 #include <istream> 23 #include <memory> 24 #include <mutex> 25 #include <optional> 26 #include <string> 27 #include <vector> 28 29 #include "aemu/base/streams/RingStreambuf.h" 30 31 namespace android { 32 namespace base { 33 34 class Command; 35 36 using android::base::streams::RingStreambuf; 37 using CommandArguments = std::vector<std::string>; 38 using Pid = int; 39 using ProcessExitCode = int; 40 41 // A process in that is running in the os. 42 class Process { 43 public: ~Process()44 virtual ~Process(){}; 45 46 // pid of the process, or -1 if it is invalid pid()47 Pid pid() const { return mPid; }; 48 49 // Name of the process, note this might not be 50 // immediately availabl. 51 virtual std::string exe() const = 0; 52 53 // The exit code of the process, this will block 54 // and wait until the process has finished or is detached. 55 // 56 // This can return INT_MIN in case of failures. 57 ProcessExitCode exitCode() const; 58 59 // Unconditionally cause the process to exit. (Kill -9 ..) 60 // Returns true if the process was terminated, false in case of failure. 61 virtual bool terminate() = 0; 62 63 // True if the pid is alive according to the os. 64 virtual bool isAlive() const = 0; 65 66 // Waits for process completion, returns if it is not finished for the 67 // specified timeout duration wait_for(const std::chrono::milliseconds timeout_duration)68 virtual std::future_status wait_for( 69 const std::chrono::milliseconds timeout_duration) const { 70 return wait_for_kernel(timeout_duration); 71 } 72 73 // Waits for process completion, returns if it is not finished until 74 // specified time point has been reached 75 template <class Clock, class Duration> wait_until(const std::chrono::time_point<Clock,Duration> & timeout_time)76 std::future_status wait_until( 77 const std::chrono::time_point<Clock, Duration>& timeout_time) 78 const { 79 return wait_for(timeout_time - std::chrono::steady_clock::now()); 80 }; 81 82 bool operator==(const Process& rhs) const { return (mPid == rhs.mPid); } 83 bool operator!=(const Process& rhs) const { return !operator==(rhs); } 84 85 // Retrieve the object from the given pid id. 86 static std::unique_ptr<Process> fromPid(Pid pid); 87 88 // Retrieve process with "name" in the process. 89 static std::vector<std::unique_ptr<Process>> fromName(std::string name); 90 91 // Retrieve myself. 92 static std::unique_ptr<Process> me(); 93 94 protected: 95 // Return the exit code of the process, this should not block 96 virtual std::optional<ProcessExitCode> getExitCode() const = 0; 97 98 // Wait until this process is finished, by using an os level 99 // call. 100 virtual std::future_status wait_for_kernel( 101 const std::chrono::milliseconds timeout_duration) const = 0; 102 103 Pid mPid; 104 }; 105 106 // Output of the process. 107 class ProcessOutput { 108 public: 109 virtual ~ProcessOutput() = default; 110 111 // Consumes the whole stream, and returns a string. 112 virtual std::string asString() = 0; 113 114 // Returns a stream, that will block until data 115 // from the child is available. 116 virtual std::istream& asStream() = 0; 117 }; 118 119 // A process overseer is responsible for observering the process: 120 // It is watching writes to std_err & std_out and passes them 121 // on to a RingStreambuf 122 class ProcessOverseer { 123 public: 124 virtual ~ProcessOverseer() = default; 125 126 // Start observering the process. 127 // 128 // The overseer should: 129 // - Write to std_out & std_err when needed. 130 // - Close the RingStreambuf when done with the stream. 131 // - Return when it can no longer read/write from stdout/stderr 132 virtual void start(RingStreambuf* out, RingStreambuf* err) = 0; 133 134 // Cancel the observation of the process if observation is still happening. 135 // Basically this is used to detach from a running process. 136 // 137 // After return: 138 // - no writes to std_out, std_err should happen 139 // - all resource should be cleaned up. 140 // - a call to the start method should return with std::nullopt 141 virtual void stop() = 0; 142 }; 143 144 // A overseer that does nothing. 145 // Use this for detached processes, testing. 146 class NullOverseer : public ProcessOverseer { 147 public: start(RingStreambuf * out,RingStreambuf * err)148 virtual void start(RingStreambuf* out, RingStreambuf* err) override {} stop()149 virtual void stop() override {} 150 }; 151 152 // A running process that you can interact with. 153 // 154 // You obtain a process by running a command. 155 // For example: 156 // 157 // auto p = Command::create({"ls"}).execute(); 158 // if (p->exitCode() == 0) { 159 // auto list = p->out()->asString(); 160 // } 161 class ObservableProcess : public Process { 162 public: 163 // Kills the process.. 164 virtual ~ObservableProcess(); 165 166 // stdout from the child if not detached. out()167 ProcessOutput* out() { return mStdOut.get(); }; 168 169 // stderr from the child if not detached. err()170 ProcessOutput* err() { return mStdErr.get(); }; 171 172 // Detach the process overseer, and stop observing the process 173 // you will: 174 // - Not able to read stdout/stderr 175 // - The process will not be terminated when going out of scope. 176 void detach(); 177 178 std::future_status wait_for( 179 const std::chrono::milliseconds timeout_duration) const override; 180 181 protected: 182 // Subclasses should implement this to actually launch the process, 183 // return std::nullopt in case of failure 184 virtual std::optional<Pid> createProcess(const CommandArguments& args, 185 bool captureOutput) = 0; 186 187 // Create the overseer used to observe the process state. 188 virtual std::unique_ptr<ProcessOverseer> createOverseer() = 0; 189 190 // True if no overseer is needed 191 bool mDeamon{false}; 192 193 private: 194 void runOverseer(); 195 196 std::unique_ptr<ProcessOverseer> mOverseer; 197 std::unique_ptr<std::thread> mOverseerThread; 198 bool mOverseerActive{false}; 199 mutable std::mutex mOverseerMutex; 200 mutable std::condition_variable mOverseerCv; 201 202 std::unique_ptr<ProcessOutput> mStdOut; 203 std::unique_ptr<ProcessOutput> mStdErr; 204 205 friend Command; 206 }; 207 } // namespace base 208 } // namespace android 209