• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 /**
43  * Represents a process running within the operating system.
44  */
45 class Process {
46 public:
47     virtual ~Process() = default;
48 
49     /**
50      * @return The process ID (PID) of the process, or -1 if invalid.
51      */
pid()52     Pid pid() const { return mPid; };
53 
54     /**
55      * @return The name of the process executable. Note that this information
56      *         might not be immediately available, especially shortly after
57      *         the process has been started.
58      */
59     virtual std::string exe() const = 0;
60 
61     /**
62      * Retrieves the exit code of the process. This method will block until
63      * the process has finished or is detached.
64      *
65      * @return The process exit code. This can return INT_MIN in case of
66      *         failures retrieving the exit code.
67      */
68     ProcessExitCode exitCode() const;
69 
70     /**
71      * Forcibly terminates the process (similar to sending SIGKILL).
72      *
73      * @return True if the process was successfully terminated, false otherwise.
74      */
75     virtual bool terminate() = 0;
76 
77     /**
78      * Checks if the process is currently alive according to the operating
79      * system.
80      *
81      * @return True if the process is alive, false otherwise.
82      */
83     virtual bool isAlive() const = 0;
84 
85     /**
86      * Waits for the process to complete, or until the specified timeout
87      * duration has elapsed.
88      *
89      * @param timeout_duration The maximum duration to wait for process
90      *        completion.
91      * @return A std::future_status value indicating whether the wait
92      *         completed due to process termination or timeout.
93      */
wait_for(const std::chrono::milliseconds timeout_duration)94     virtual std::future_status wait_for(
95             const std::chrono::milliseconds timeout_duration) const {
96         return wait_for_kernel(timeout_duration);
97     }
98 
99     /**
100      * Waits for the process to complete, or until the specified time point
101      * has been reached.
102      *
103      * @tparam Clock The clock type used for the timeout.
104      * @tparam Duration The duration type used for the timeout.
105      * @param timeout_time The time point at which the wait should timeout.
106      * @return A std::future_status value indicating whether the wait
107      *         completed due to process termination or timeout.
108      */
109     template <class Clock, class Duration>
wait_until(const std::chrono::time_point<Clock,Duration> & timeout_time)110     std::future_status wait_until(
111             const std::chrono::time_point<Clock, Duration>& timeout_time)
112             const {
113         return wait_for(timeout_time - std::chrono::steady_clock::now());
114     };
115 
116     bool operator==(const Process& rhs) const { return (mPid == rhs.mPid); }
117     bool operator!=(const Process& rhs) const { return !operator==(rhs); }
118 
119     /**
120      * Retrieves a Process object representing the process with the given PID.
121      *
122      * @param pid The process ID (PID) to search for.
123      * @return A unique pointer to a Process object representing the process,
124      *         or nullptr if no such process exists.
125      */
126     static std::unique_ptr<Process> fromPid(Pid pid);
127 
128     /**
129      * Retrieves a list of Process objects representing processes whose
130      * executable name contains the specified name substring.
131      *
132      * Note: There might be a delay between the creation of a process and its
133      * appearance in the process list. This delay can vary depending on the
134      * operating system and system load.
135      *
136      * @param name The name substring to search for in process names.
137      * @return A vector of unique pointers to Process objects representing the
138      *         matching processes. If no matching processes are found, the
139      *         vector will be empty.
140      */
141     static std::vector<std::unique_ptr<Process>> fromName(std::string name);
142 
143     /**
144      * @return A unique pointer to a Process object representing the current
145      *         process.
146      */
147     static std::unique_ptr<Process> me();
148 
149 protected:
150     /**
151      * Retrieves the exit code of the process without blocking.
152      *
153      * @return An optional containing the process exit code if available,
154      *         or std::nullopt if the process is still running or the exit
155      *         code cannot be retrieved.
156      */
157     virtual std::optional<ProcessExitCode> getExitCode() const = 0;
158 
159     /**
160      * Waits for the process to complete using an operating system-level call,
161      * without using any additional polling mechanisms.
162      *
163      * @param timeout_duration The maximum duration to wait for process
164      *        completion.
165      * @return A std::future_status value indicating whether the wait
166      *         completed due to process termination or timeout.
167      */
168     virtual std::future_status wait_for_kernel(
169             const std::chrono::milliseconds timeout_duration) const = 0;
170 
171     Pid mPid;
172 };
173 
174 /**
175  * Represents the output (stdout and stderr) of a process.
176  */
177 class ProcessOutput {
178 public:
179     virtual ~ProcessOutput() = default;
180 
181     /**
182      * Consumes the entire output stream and returns it as a string.
183      *
184      * @return The entire process output as a string.
185      */
186     virtual std::string asString() = 0;
187 
188     /**
189      * Provides access to the output stream, which can be used to read the
190      * process output incrementally. This method may block until data is
191      * available from the child process.
192      *
193      * @return A reference to the output stream.
194      */
195     virtual std::istream& asStream() = 0;
196 };
197 
198 /**
199  * The ProcessOverseer class is responsible for monitoring a child process
200  * and capturing its output (stdout and stderr).
201  */
202 class ProcessOverseer {
203 public:
204     virtual ~ProcessOverseer() = default;
205 
206     /**
207      * Starts monitoring the child process and capturing its output.
208      *
209      * The overseer should:
210      * - Write captured output to the provided `out` and `err`
211      *   RingStreambuf objects.
212      * - Close the RingStreambuf objects when the corresponding output streams
213      *   are closed by the child process.
214      * - Return from this method when it can no longer read or write from the
215      *   child process's stdout and stderr.
216      *
217      * @param out The RingStreambuf object to write captured stdout output to.
218      * @param err The RingStreambuf object to write captured stderr output to.
219      */
220     virtual void start(RingStreambuf* out, RingStreambuf* err) = 0;
221 
222     /**
223      * Stops monitoring the child process and releases any resources held by
224      * the overseer.
225      *
226      * After this method returns:
227      * - No further writes should be made to the `out` and `err`
228      *   RingStreambuf objects.
229      * - All resources associated with the overseer should be released.
230      * - Calling the `start` method again should result in an error or return
231      *   immediately.
232      */
233     virtual void stop() = 0;
234 };
235 
236 /**
237  * A ProcessOverseer implementation that does nothing. This can be used for
238  * detached processes or in testing scenarios where process output monitoring
239  * is not required.
240  */
241 class NullOverseer : public ProcessOverseer {
242 public:
start(RingStreambuf * out,RingStreambuf * err)243     virtual void start(RingStreambuf* out, RingStreambuf* err) override {}
stop()244     virtual void stop() override {}
245 };
246 
247 /**
248  * Represents a running process that can be interacted with, such as reading
249  * its output or terminating it.
250  *
251  * You typically obtain an ObservableProcess object by executing a Command.
252  *
253  * Example:
254  * ```cpp
255  * auto p = Command::create({"ls"}).execute();
256  * if (p->exitCode() == 0) {
257  *     auto list = p->out()->asString();
258  * }
259  * ```
260  */
261 class ObservableProcess : public Process {
262 public:
263     // Kills the process..
264     virtual ~ObservableProcess();
265 
266     /**
267      * @return A pointer to the ProcessOutput object representing the child
268      *         process's standard output (stdout), or nullptr if the process
269      *         was started in detached mode.
270      */
out()271     ProcessOutput* out() { return mStdOut.get(); };
272 
273     /**
274      * @return A pointer to the ProcessOutput object representing the child
275      *         process's standard error (stderr), or nullptr if the process
276      *         was started in detached mode.
277      */
err()278     ProcessOutput* err() { return mStdErr.get(); };
279 
280     /**
281      * Detaches the process overseer, stopping the monitoring of the child
282      * process's output and preventing the process from being automatically
283      * terminated when the ObservableProcess object goes out of scope.
284      *
285      * After calling this method:
286      * - You will no longer be able to read the child process's stdout and
287      *   stderr.
288      * - The child process will continue running even after the
289      *   ObservableProcess object is destroyed.
290      */
291     void detach();
292 
293     std::future_status wait_for(
294             const std::chrono::milliseconds timeout_duration) const override;
295 
296 protected:
297     /**
298      * Subclasses should implement this method to handle the actual process
299      * creation and launch.
300      *
301      * @param args The command line arguments to pass to the child process.
302      * @param captureOutput Whether to capture the child process's output
303      *        (stdout and stderr).
304      * @return An optional containing the PID of the newly created process if
305      *         successful, or std::nullopt if process creation failed.
306      */
307     virtual std::optional<Pid> createProcess(const CommandArguments& args,
308                                              bool captureOutput,
309                                              bool replace) = 0;
310 
311     /**
312      * Creates the ProcessOverseer object responsible for monitoring the child
313      * process and capturing its output.
314      *
315      * @return A unique pointer to the created ProcessOverseer object.
316      */
317     virtual std::unique_ptr<ProcessOverseer> createOverseer() = 0;
318 
319     // True if no overseer is needed
320     bool mDeamon{false};
321 
322     // True if we want to inherit all the fds/handles.
323     bool mInherit{false};
324 
325 private:
326     void runOverseer();
327 
328     std::unique_ptr<ProcessOverseer> mOverseer;
329     std::unique_ptr<std::thread> mOverseerThread;
GUARDED_BY(mOverseerMutex)330     bool mOverseerActive GUARDED_BY(mOverseerMutex) {false};
331     mutable std::mutex mOverseerMutex;
332     mutable std::condition_variable mOverseerCv;
333 
334     std::unique_ptr<ProcessOutput> mStdOut;
335     std::unique_ptr<ProcessOutput> mStdErr;
336 
337     friend Command;
338 };
339 }  // namespace base
340 }  // namespace android
341