blob: c26ea6076818010b8cad62e27b9fe794e1caac43 [file] [log] [blame]
Darin Petkov85d02b72011-05-17 13:25:51 -07001// Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
adlr@google.com3defe6a2009-12-04 20:57:17 +00002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
Gilad Arnoldcf175a02014-07-10 16:48:47 -07005#ifndef UPDATE_ENGINE_SUBPROCESS_H_
6#define UPDATE_ENGINE_SUBPROCESS_H_
adlr@google.com3defe6a2009-12-04 20:57:17 +00007
Alex Deymo461b2592015-07-24 20:10:52 -07008#include <unistd.h>
Ben Chan05735a12014-09-03 07:48:22 -07009
adlr@google.com3defe6a2009-12-04 20:57:17 +000010#include <map>
Alex Deymobc91a272014-05-20 16:45:33 -070011#include <memory>
adlr@google.com3defe6a2009-12-04 20:57:17 +000012#include <string>
13#include <vector>
Darin Petkov6f03a3b2010-11-10 14:27:14 -080014
Alex Deymo461b2592015-07-24 20:10:52 -070015#include <base/callback.h>
Ben Chan05735a12014-09-03 07:48:22 -070016#include <base/logging.h>
17#include <base/macros.h>
Alex Deymo461b2592015-07-24 20:10:52 -070018#include <chromeos/asynchronous_signal_handler.h>
Alex Deymo29b81532015-07-09 11:51:49 -070019#include <chromeos/message_loops/message_loop.h>
Alex Deymo461b2592015-07-24 20:10:52 -070020#include <chromeos/process.h>
21#include <chromeos/process_reaper.h>
Alex Deymo60ca1a72015-06-18 18:19:15 -070022#include <gtest/gtest_prod.h> // for FRIEND_TEST
adlr@google.com3defe6a2009-12-04 20:57:17 +000023
24// The Subprocess class is a singleton. It's used to spawn off a subprocess
25// and get notified when the subprocess exits. The result of Exec() can
Alex Deymo29b81532015-07-09 11:51:49 -070026// be saved and used to cancel the callback request and kill your process. If
27// you know you won't call KillExec(), you may safely lose the return value
28// from Exec().
adlr@google.com3defe6a2009-12-04 20:57:17 +000029
Alex Deymo461b2592015-07-24 20:10:52 -070030// To create the Subprocess singleton just instantiate it with and call Init().
31// You can't have two Subprocess instances initialized at the same time.
32
adlr@google.com3defe6a2009-12-04 20:57:17 +000033namespace chromeos_update_engine {
34
35class Subprocess {
36 public:
Alex Deymo461b2592015-07-24 20:10:52 -070037 enum Flags {
38 kSearchPath = 1 << 0,
39 kRedirectStderrToStdout = 1 << 1,
40 };
Darin Petkov6f03a3b2010-11-10 14:27:14 -080041
Alex Deymo461b2592015-07-24 20:10:52 -070042 // Callback type used when an async process terminates. It receives the exit
43 // code and the stdout output (and stderr if redirected).
44 using ExecCallback = base::Callback<void(int, const std::string&)>;
adlr@google.com3defe6a2009-12-04 20:57:17 +000045
Alex Deymo461b2592015-07-24 20:10:52 -070046 Subprocess() = default;
47
48 // Destroy and unregister the Subprocess singleton.
49 ~Subprocess();
50
51 // Initialize and register the Subprocess singleton.
52 void Init();
53
54 // Launches a process in the background and calls the passed |callback| when
55 // the process exits.
56 // Returns the process id of the new launched process or 0 in case of failure.
57 pid_t Exec(const std::vector<std::string>& cmd, const ExecCallback& callback);
58 pid_t ExecFlags(const std::vector<std::string>& cmd,
59 uint32_t flags,
60 const ExecCallback& callback);
adlr@google.com3defe6a2009-12-04 20:57:17 +000061
Alex Deymo29b81532015-07-09 11:51:49 -070062 // Kills the running process with SIGTERM and ignores the callback.
Alex Deymo461b2592015-07-24 20:10:52 -070063 void KillExec(pid_t tag);
adlr@google.com3defe6a2009-12-04 20:57:17 +000064
Darin Petkov85d02b72011-05-17 13:25:51 -070065 // Executes a command synchronously. Returns true on success. If |stdout| is
66 // non-null, the process output is stored in it, otherwise the output is
67 // logged. Note that stderr is redirected to stdout.
adlr@google.com3defe6a2009-12-04 20:57:17 +000068 static bool SynchronousExec(const std::vector<std::string>& cmd,
Darin Petkov85d02b72011-05-17 13:25:51 -070069 int* return_code,
70 std::string* stdout);
Alex Deymo461b2592015-07-24 20:10:52 -070071 static bool SynchronousExecFlags(const std::vector<std::string>& cmd,
72 uint32_t flags,
73 int* return_code,
74 std::string* stdout);
adlr@google.com3defe6a2009-12-04 20:57:17 +000075
Alex Deymo29b81532015-07-09 11:51:49 -070076 // Gets the one instance.
adlr@google.com3defe6a2009-12-04 20:57:17 +000077 static Subprocess& Get() {
78 return *subprocess_singleton_;
79 }
Darin Petkov6f03a3b2010-11-10 14:27:14 -080080
adlr@google.com3defe6a2009-12-04 20:57:17 +000081 // Returns true iff there is at least one subprocess we're waiting on.
Darin Petkov6f03a3b2010-11-10 14:27:14 -080082 bool SubprocessInFlight();
83
adlr@google.com3defe6a2009-12-04 20:57:17 +000084 private:
Alex Deymo60ca1a72015-06-18 18:19:15 -070085 FRIEND_TEST(SubprocessTest, CancelTest);
86
Darin Petkov6f03a3b2010-11-10 14:27:14 -080087 struct SubprocessRecord {
Alex Deymo461b2592015-07-24 20:10:52 -070088 explicit SubprocessRecord(const ExecCallback& callback)
89 : callback(callback) {}
Alex Deymo29b81532015-07-09 11:51:49 -070090
Alex Deymo461b2592015-07-24 20:10:52 -070091 // The callback supplied by the caller.
92 ExecCallback callback;
Alex Deymo29b81532015-07-09 11:51:49 -070093
Alex Deymo461b2592015-07-24 20:10:52 -070094 // The ProcessImpl instance managing the child process. Destroying this
95 // will close our end of the pipes we have open.
96 chromeos::ProcessImpl proc;
Alex Deymo29b81532015-07-09 11:51:49 -070097
Alex Deymo461b2592015-07-24 20:10:52 -070098 // These are used to monitor the stdout of the running process, including
99 // the stderr if it was redirected.
100 chromeos::MessageLoop::TaskId stdout_task_id{
101 chromeos::MessageLoop::kTaskIdNull};
Alex Deymo29b81532015-07-09 11:51:49 -0700102 int stdout_fd{-1};
Darin Petkov6f03a3b2010-11-10 14:27:14 -0800103 std::string stdout;
104 };
105
Darin Petkov6f03a3b2010-11-10 14:27:14 -0800106 // Callback which runs whenever there is input available on the subprocess
107 // stdout pipe.
Alex Deymo29b81532015-07-09 11:51:49 -0700108 static void OnStdoutReady(SubprocessRecord* record);
adlr@google.com3defe6a2009-12-04 20:57:17 +0000109
Alex Deymo461b2592015-07-24 20:10:52 -0700110 // Callback for when any subprocess terminates. This calls the user
111 // requested callback.
112 void ChildExitedCallback(const siginfo_t& info);
113
Darin Petkov6f03a3b2010-11-10 14:27:14 -0800114 // The global instance.
115 static Subprocess* subprocess_singleton_;
adlr@google.com3defe6a2009-12-04 20:57:17 +0000116
Darin Petkov6f03a3b2010-11-10 14:27:14 -0800117 // A map from the asynchronous subprocess tag (see Exec) to the subprocess
118 // record structure for all active asynchronous subprocesses.
Alex Deymo461b2592015-07-24 20:10:52 -0700119 std::map<pid_t, std::unique_ptr<SubprocessRecord>> subprocess_records_;
120
121 // Used to watch for child processes.
122 chromeos::AsynchronousSignalHandler async_signal_handler_;
123 chromeos::ProcessReaper process_reaper_;
Darin Petkov6f03a3b2010-11-10 14:27:14 -0800124
adlr@google.com3defe6a2009-12-04 20:57:17 +0000125 DISALLOW_COPY_AND_ASSIGN(Subprocess);
126};
127
128} // namespace chromeos_update_engine
129
Gilad Arnoldcf175a02014-07-10 16:48:47 -0700130#endif // UPDATE_ENGINE_SUBPROCESS_H_