blob: f1b9f1f724d69d0c471b4308935f13b15e486e3b [file] [log] [blame]
Alex Deymoaea4c1c2015-08-19 20:24:43 -07001//
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//
adlr@google.com3defe6a2009-12-04 20:57:17 +000016
Alex Deymo39910dc2015-11-09 17:04:30 -080017#ifndef UPDATE_ENGINE_COMMON_SUBPROCESS_H_
18#define UPDATE_ENGINE_COMMON_SUBPROCESS_H_
adlr@google.com3defe6a2009-12-04 20:57:17 +000019
Alex Deymo461b2592015-07-24 20:10:52 -070020#include <unistd.h>
Ben Chan05735a12014-09-03 07:48:22 -070021
adlr@google.com3defe6a2009-12-04 20:57:17 +000022#include <map>
Alex Deymobc91a272014-05-20 16:45:33 -070023#include <memory>
adlr@google.com3defe6a2009-12-04 20:57:17 +000024#include <string>
25#include <vector>
Darin Petkov6f03a3b2010-11-10 14:27:14 -080026
Alex Deymo461b2592015-07-24 20:10:52 -070027#include <base/callback.h>
Hidehiko Abe493fecb2019-07-10 23:30:50 +090028#include <base/files/file_descriptor_watcher_posix.h>
Ben Chan05735a12014-09-03 07:48:22 -070029#include <base/logging.h>
30#include <base/macros.h>
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -070031#include <brillo/asynchronous_signal_handler_interface.h>
32#include <brillo/message_loops/message_loop.h>
33#include <brillo/process.h>
34#include <brillo/process_reaper.h>
Alex Deymo60ca1a72015-06-18 18:19:15 -070035#include <gtest/gtest_prod.h> // for FRIEND_TEST
adlr@google.com3defe6a2009-12-04 20:57:17 +000036
37// The Subprocess class is a singleton. It's used to spawn off a subprocess
38// and get notified when the subprocess exits. The result of Exec() can
Alex Deymo29b81532015-07-09 11:51:49 -070039// be saved and used to cancel the callback request and kill your process. If
40// you know you won't call KillExec(), you may safely lose the return value
41// from Exec().
adlr@google.com3defe6a2009-12-04 20:57:17 +000042
Alex Deymo461b2592015-07-24 20:10:52 -070043// To create the Subprocess singleton just instantiate it with and call Init().
44// You can't have two Subprocess instances initialized at the same time.
45
adlr@google.com3defe6a2009-12-04 20:57:17 +000046namespace chromeos_update_engine {
47
48class Subprocess {
49 public:
Alex Deymo461b2592015-07-24 20:10:52 -070050 enum Flags {
51 kSearchPath = 1 << 0,
52 kRedirectStderrToStdout = 1 << 1,
53 };
Darin Petkov6f03a3b2010-11-10 14:27:14 -080054
Alex Deymo461b2592015-07-24 20:10:52 -070055 // Callback type used when an async process terminates. It receives the exit
56 // code and the stdout output (and stderr if redirected).
57 using ExecCallback = base::Callback<void(int, const std::string&)>;
adlr@google.com3defe6a2009-12-04 20:57:17 +000058
Alex Deymo461b2592015-07-24 20:10:52 -070059 Subprocess() = default;
60
61 // Destroy and unregister the Subprocess singleton.
62 ~Subprocess();
63
64 // Initialize and register the Subprocess singleton.
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -070065 void Init(brillo::AsynchronousSignalHandlerInterface* async_signal_handler);
Alex Deymo461b2592015-07-24 20:10:52 -070066
67 // Launches a process in the background and calls the passed |callback| when
Alex Deymoe384bb22016-03-29 17:23:33 -070068 // the process exits. The file descriptors specified in |output_pipes| will
69 // be available in the child as the writer end of a pipe. Use GetPipeFd() to
70 // know the reader end in the parent. Only stdin, stdout, stderr and the file
71 // descriptors in |output_pipes| will be open in the child.
Alex Deymo461b2592015-07-24 20:10:52 -070072 // Returns the process id of the new launched process or 0 in case of failure.
73 pid_t Exec(const std::vector<std::string>& cmd, const ExecCallback& callback);
74 pid_t ExecFlags(const std::vector<std::string>& cmd,
75 uint32_t flags,
Alex Deymoe384bb22016-03-29 17:23:33 -070076 const std::vector<int>& output_pipes,
Alex Deymo461b2592015-07-24 20:10:52 -070077 const ExecCallback& callback);
adlr@google.com3defe6a2009-12-04 20:57:17 +000078
Alex Deymo29b81532015-07-09 11:51:49 -070079 // Kills the running process with SIGTERM and ignores the callback.
Alex Deymoe384bb22016-03-29 17:23:33 -070080 void KillExec(pid_t pid);
81
82 // Return the parent end of the pipe mapped onto |fd| in the child |pid|. This
83 // file descriptor is available until the callback for the child |pid|
84 // returns. After that the file descriptor will be closed. The passed |fd|
85 // must be one of the file descriptors passed to ExecFlags() in
86 // |output_pipes|, otherwise returns -1.
87 int GetPipeFd(pid_t pid, int fd) const;
adlr@google.com3defe6a2009-12-04 20:57:17 +000088
Darin Petkov85d02b72011-05-17 13:25:51 -070089 // Executes a command synchronously. Returns true on success. If |stdout| is
90 // non-null, the process output is stored in it, otherwise the output is
Amin Hassani3a4caa12019-11-06 11:12:28 -080091 // logged.
adlr@google.com3defe6a2009-12-04 20:57:17 +000092 static bool SynchronousExec(const std::vector<std::string>& cmd,
Darin Petkov85d02b72011-05-17 13:25:51 -070093 int* return_code,
Amin Hassani3a4caa12019-11-06 11:12:28 -080094 std::string* stdout,
95 std::string* stderr);
Alex Deymo461b2592015-07-24 20:10:52 -070096 static bool SynchronousExecFlags(const std::vector<std::string>& cmd,
97 uint32_t flags,
98 int* return_code,
Amin Hassani3a4caa12019-11-06 11:12:28 -080099 std::string* stdout,
100 std::string* stderr);
adlr@google.com3defe6a2009-12-04 20:57:17 +0000101
Alex Deymo29b81532015-07-09 11:51:49 -0700102 // Gets the one instance.
Amin Hassanib2689592019-01-13 17:04:28 -0800103 static Subprocess& Get() { return *subprocess_singleton_; }
Darin Petkov6f03a3b2010-11-10 14:27:14 -0800104
Amin Hassania8859542018-03-07 16:24:43 -0800105 // Tries to log all in flight processes's output. It is used right before
106 // exiting the update_engine, probably when the subprocess caused a system
107 // shutdown.
108 void FlushBufferedLogsAtExit();
109
adlr@google.com3defe6a2009-12-04 20:57:17 +0000110 private:
Alex Deymo60ca1a72015-06-18 18:19:15 -0700111 FRIEND_TEST(SubprocessTest, CancelTest);
112
Darin Petkov6f03a3b2010-11-10 14:27:14 -0800113 struct SubprocessRecord {
Alex Deymo461b2592015-07-24 20:10:52 -0700114 explicit SubprocessRecord(const ExecCallback& callback)
Amin Hassanib2689592019-01-13 17:04:28 -0800115 : callback(callback) {}
Alex Deymo29b81532015-07-09 11:51:49 -0700116
Alex Deymo461b2592015-07-24 20:10:52 -0700117 // The callback supplied by the caller.
118 ExecCallback callback;
Alex Deymo29b81532015-07-09 11:51:49 -0700119
Alex Deymo461b2592015-07-24 20:10:52 -0700120 // The ProcessImpl instance managing the child process. Destroying this
121 // will close our end of the pipes we have open.
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700122 brillo::ProcessImpl proc;
Alex Deymo29b81532015-07-09 11:51:49 -0700123
Alex Deymo461b2592015-07-24 20:10:52 -0700124 // These are used to monitor the stdout of the running process, including
125 // the stderr if it was redirected.
Tianjie55abd3c2020-06-19 00:22:59 -0700126#ifdef __ANDROID__
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700127 brillo::MessageLoop::TaskId stdout_task_id{
128 brillo::MessageLoop::kTaskIdNull};
Tianjie55abd3c2020-06-19 00:22:59 -0700129#else
Hidehiko Abe493fecb2019-07-10 23:30:50 +0900130 std::unique_ptr<base::FileDescriptorWatcher::Controller> stdout_controller;
Tianjie55abd3c2020-06-19 00:22:59 -0700131#endif // __ANDROID__
Alex Deymo29b81532015-07-09 11:51:49 -0700132 int stdout_fd{-1};
Darin Petkov6f03a3b2010-11-10 14:27:14 -0800133 std::string stdout;
134 };
135
Darin Petkov6f03a3b2010-11-10 14:27:14 -0800136 // Callback which runs whenever there is input available on the subprocess
137 // stdout pipe.
Alex Deymo29b81532015-07-09 11:51:49 -0700138 static void OnStdoutReady(SubprocessRecord* record);
adlr@google.com3defe6a2009-12-04 20:57:17 +0000139
Alex Deymo461b2592015-07-24 20:10:52 -0700140 // Callback for when any subprocess terminates. This calls the user
141 // requested callback.
142 void ChildExitedCallback(const siginfo_t& info);
143
Darin Petkov6f03a3b2010-11-10 14:27:14 -0800144 // The global instance.
145 static Subprocess* subprocess_singleton_;
adlr@google.com3defe6a2009-12-04 20:57:17 +0000146
Darin Petkov6f03a3b2010-11-10 14:27:14 -0800147 // A map from the asynchronous subprocess tag (see Exec) to the subprocess
148 // record structure for all active asynchronous subprocesses.
Alex Deymo461b2592015-07-24 20:10:52 -0700149 std::map<pid_t, std::unique_ptr<SubprocessRecord>> subprocess_records_;
150
151 // Used to watch for child processes.
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700152 brillo::ProcessReaper process_reaper_;
Darin Petkov6f03a3b2010-11-10 14:27:14 -0800153
adlr@google.com3defe6a2009-12-04 20:57:17 +0000154 DISALLOW_COPY_AND_ASSIGN(Subprocess);
155};
156
157} // namespace chromeos_update_engine
158
Alex Deymo39910dc2015-11-09 17:04:30 -0800159#endif // UPDATE_ENGINE_COMMON_SUBPROCESS_H_