blob: 8c72c312d1b26f4db7f0db558393eb3e82188e22 [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
Gilad Arnoldcf175a02014-07-10 16:48:47 -070017#ifndef UPDATE_ENGINE_SUBPROCESS_H_
18#define UPDATE_ENGINE_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>
Ben Chan05735a12014-09-03 07:48:22 -070028#include <base/logging.h>
29#include <base/macros.h>
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -070030#include <brillo/asynchronous_signal_handler_interface.h>
31#include <brillo/message_loops/message_loop.h>
32#include <brillo/process.h>
33#include <brillo/process_reaper.h>
Alex Deymo60ca1a72015-06-18 18:19:15 -070034#include <gtest/gtest_prod.h> // for FRIEND_TEST
adlr@google.com3defe6a2009-12-04 20:57:17 +000035
36// The Subprocess class is a singleton. It's used to spawn off a subprocess
37// and get notified when the subprocess exits. The result of Exec() can
Alex Deymo29b81532015-07-09 11:51:49 -070038// be saved and used to cancel the callback request and kill your process. If
39// you know you won't call KillExec(), you may safely lose the return value
40// from Exec().
adlr@google.com3defe6a2009-12-04 20:57:17 +000041
Alex Deymo461b2592015-07-24 20:10:52 -070042// To create the Subprocess singleton just instantiate it with and call Init().
43// You can't have two Subprocess instances initialized at the same time.
44
adlr@google.com3defe6a2009-12-04 20:57:17 +000045namespace chromeos_update_engine {
46
47class Subprocess {
48 public:
Alex Deymo461b2592015-07-24 20:10:52 -070049 enum Flags {
50 kSearchPath = 1 << 0,
51 kRedirectStderrToStdout = 1 << 1,
52 };
Darin Petkov6f03a3b2010-11-10 14:27:14 -080053
Alex Deymo461b2592015-07-24 20:10:52 -070054 // Callback type used when an async process terminates. It receives the exit
55 // code and the stdout output (and stderr if redirected).
56 using ExecCallback = base::Callback<void(int, const std::string&)>;
adlr@google.com3defe6a2009-12-04 20:57:17 +000057
Alex Deymo461b2592015-07-24 20:10:52 -070058 Subprocess() = default;
59
60 // Destroy and unregister the Subprocess singleton.
61 ~Subprocess();
62
63 // Initialize and register the Subprocess singleton.
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -070064 void Init(brillo::AsynchronousSignalHandlerInterface* async_signal_handler);
Alex Deymo461b2592015-07-24 20:10:52 -070065
66 // Launches a process in the background and calls the passed |callback| when
67 // the process exits.
68 // Returns the process id of the new launched process or 0 in case of failure.
69 pid_t Exec(const std::vector<std::string>& cmd, const ExecCallback& callback);
70 pid_t ExecFlags(const std::vector<std::string>& cmd,
71 uint32_t flags,
72 const ExecCallback& callback);
adlr@google.com3defe6a2009-12-04 20:57:17 +000073
Alex Deymo29b81532015-07-09 11:51:49 -070074 // Kills the running process with SIGTERM and ignores the callback.
Alex Deymo461b2592015-07-24 20:10:52 -070075 void KillExec(pid_t tag);
adlr@google.com3defe6a2009-12-04 20:57:17 +000076
Darin Petkov85d02b72011-05-17 13:25:51 -070077 // Executes a command synchronously. Returns true on success. If |stdout| is
78 // non-null, the process output is stored in it, otherwise the output is
79 // logged. Note that stderr is redirected to stdout.
adlr@google.com3defe6a2009-12-04 20:57:17 +000080 static bool SynchronousExec(const std::vector<std::string>& cmd,
Darin Petkov85d02b72011-05-17 13:25:51 -070081 int* return_code,
82 std::string* stdout);
Alex Deymo461b2592015-07-24 20:10:52 -070083 static bool SynchronousExecFlags(const std::vector<std::string>& cmd,
84 uint32_t flags,
85 int* return_code,
86 std::string* stdout);
adlr@google.com3defe6a2009-12-04 20:57:17 +000087
Alex Deymo29b81532015-07-09 11:51:49 -070088 // Gets the one instance.
adlr@google.com3defe6a2009-12-04 20:57:17 +000089 static Subprocess& Get() {
90 return *subprocess_singleton_;
91 }
Darin Petkov6f03a3b2010-11-10 14:27:14 -080092
adlr@google.com3defe6a2009-12-04 20:57:17 +000093 // Returns true iff there is at least one subprocess we're waiting on.
Darin Petkov6f03a3b2010-11-10 14:27:14 -080094 bool SubprocessInFlight();
95
adlr@google.com3defe6a2009-12-04 20:57:17 +000096 private:
Alex Deymo60ca1a72015-06-18 18:19:15 -070097 FRIEND_TEST(SubprocessTest, CancelTest);
98
Darin Petkov6f03a3b2010-11-10 14:27:14 -080099 struct SubprocessRecord {
Alex Deymo461b2592015-07-24 20:10:52 -0700100 explicit SubprocessRecord(const ExecCallback& callback)
101 : callback(callback) {}
Alex Deymo29b81532015-07-09 11:51:49 -0700102
Alex Deymo461b2592015-07-24 20:10:52 -0700103 // The callback supplied by the caller.
104 ExecCallback callback;
Alex Deymo29b81532015-07-09 11:51:49 -0700105
Alex Deymo461b2592015-07-24 20:10:52 -0700106 // The ProcessImpl instance managing the child process. Destroying this
107 // will close our end of the pipes we have open.
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700108 brillo::ProcessImpl proc;
Alex Deymo29b81532015-07-09 11:51:49 -0700109
Alex Deymo461b2592015-07-24 20:10:52 -0700110 // These are used to monitor the stdout of the running process, including
111 // the stderr if it was redirected.
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700112 brillo::MessageLoop::TaskId stdout_task_id{
113 brillo::MessageLoop::kTaskIdNull};
Alex Deymo29b81532015-07-09 11:51:49 -0700114 int stdout_fd{-1};
Darin Petkov6f03a3b2010-11-10 14:27:14 -0800115 std::string stdout;
116 };
117
Darin Petkov6f03a3b2010-11-10 14:27:14 -0800118 // Callback which runs whenever there is input available on the subprocess
119 // stdout pipe.
Alex Deymo29b81532015-07-09 11:51:49 -0700120 static void OnStdoutReady(SubprocessRecord* record);
adlr@google.com3defe6a2009-12-04 20:57:17 +0000121
Alex Deymo461b2592015-07-24 20:10:52 -0700122 // Callback for when any subprocess terminates. This calls the user
123 // requested callback.
124 void ChildExitedCallback(const siginfo_t& info);
125
Darin Petkov6f03a3b2010-11-10 14:27:14 -0800126 // The global instance.
127 static Subprocess* subprocess_singleton_;
adlr@google.com3defe6a2009-12-04 20:57:17 +0000128
Darin Petkov6f03a3b2010-11-10 14:27:14 -0800129 // A map from the asynchronous subprocess tag (see Exec) to the subprocess
130 // record structure for all active asynchronous subprocesses.
Alex Deymo461b2592015-07-24 20:10:52 -0700131 std::map<pid_t, std::unique_ptr<SubprocessRecord>> subprocess_records_;
132
133 // Used to watch for child processes.
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700134 brillo::ProcessReaper process_reaper_;
Darin Petkov6f03a3b2010-11-10 14:27:14 -0800135
adlr@google.com3defe6a2009-12-04 20:57:17 +0000136 DISALLOW_COPY_AND_ASSIGN(Subprocess);
137};
138
139} // namespace chromeos_update_engine
140
Gilad Arnoldcf175a02014-07-10 16:48:47 -0700141#endif // UPDATE_ENGINE_SUBPROCESS_H_