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