• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
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 //
16 
17 #ifndef UPDATE_ENGINE_COMMON_SUBPROCESS_H_
18 #define UPDATE_ENGINE_COMMON_SUBPROCESS_H_
19 
20 #include <unistd.h>
21 
22 #include <map>
23 #include <memory>
24 #include <string>
25 #include <vector>
26 
27 #include <base/callback.h>
28 #include <base/files/file_descriptor_watcher_posix.h>
29 #include <base/logging.h>
30 #include <base/macros.h>
31 #include <brillo/asynchronous_signal_handler_interface.h>
32 #include <brillo/message_loops/message_loop.h>
33 #ifdef __CHROMEOS__
34 #include <brillo/process/process.h>
35 #include <brillo/process/process_reaper.h>
36 #else
37 #include <brillo/process.h>
38 #include <brillo/process_reaper.h>
39 #endif  // __CHROMEOS__
40 #include <gtest/gtest_prod.h>
41 
42 // The Subprocess class is a singleton. It's used to spawn off a subprocess
43 // and get notified when the subprocess exits. The result of Exec() can
44 // be saved and used to cancel the callback request and kill your process. If
45 // you know you won't call KillExec(), you may safely lose the return value
46 // from Exec().
47 
48 // To create the Subprocess singleton just instantiate it with and call Init().
49 // You can't have two Subprocess instances initialized at the same time.
50 
51 namespace chromeos_update_engine {
52 
53 class Subprocess {
54  public:
55   enum Flags {
56     kSearchPath = 1 << 0,
57     kRedirectStderrToStdout = 1 << 1,
58   };
59 
60   // Callback type used when an async process terminates. It receives the exit
61   // code and the stdout output (and stderr if redirected).
62   using ExecCallback = base::Callback<void(int, const std::string&)>;
63 
64   Subprocess() = default;
65 
66   // Destroy and unregister the Subprocess singleton.
67   ~Subprocess();
68 
69   // Initialize and register the Subprocess singleton.
70   void Init(brillo::AsynchronousSignalHandlerInterface* async_signal_handler);
71 
72   // Launches a process in the background and calls the passed |callback| when
73   // the process exits. The file descriptors specified in |output_pipes| will
74   // be available in the child as the writer end of a pipe. Use GetPipeFd() to
75   // know the reader end in the parent. Only stdin, stdout, stderr and the file
76   // descriptors in |output_pipes| will be open in the child.
77   // Returns the process id of the new launched process or 0 in case of failure.
78   pid_t Exec(const std::vector<std::string>& cmd, const ExecCallback& callback);
79   pid_t ExecFlags(const std::vector<std::string>& cmd,
80                   uint32_t flags,
81                   const std::vector<int>& output_pipes,
82                   const ExecCallback& callback);
83 
84   // Kills the running process with SIGTERM and ignores the callback.
85   void KillExec(pid_t pid);
86 
87   // Return the parent end of the pipe mapped onto |fd| in the child |pid|. This
88   // file descriptor is available until the callback for the child |pid|
89   // returns. After that the file descriptor will be closed. The passed |fd|
90   // must be one of the file descriptors passed to ExecFlags() in
91   // |output_pipes|, otherwise returns -1.
92   int GetPipeFd(pid_t pid, int fd) const;
93 
94   // Executes a command synchronously. Returns true on success. If |stdout_str|
95   // is non-null, the process output is stored in it, otherwise the output is
96   // logged.
97   static bool SynchronousExec(const std::vector<std::string>& cmd,
98                               int* return_code,
99                               std::string* stdout_str,
100                               std::string* stderr_str);
101   static bool SynchronousExecFlags(const std::vector<std::string>& cmd,
102                                    uint32_t flags,
103                                    int* return_code,
104                                    std::string* stdout_str,
105                                    std::string* stderr_str);
106 
107   // Gets the one instance.
Get()108   static Subprocess& Get() { return *subprocess_singleton_; }
109 
110   // Tries to log all in flight processes's output. It is used right before
111   // exiting the update_engine, probably when the subprocess caused a system
112   // shutdown.
113   void FlushBufferedLogsAtExit();
114 
115  private:
116   FRIEND_TEST(SubprocessTest, CancelTest);
117 
118   struct SubprocessRecord {
SubprocessRecordSubprocessRecord119     explicit SubprocessRecord(const ExecCallback& callback)
120         : callback(callback) {}
121 
122     // The callback supplied by the caller.
123     ExecCallback callback;
124 
125     // The ProcessImpl instance managing the child process. Destroying this
126     // will close our end of the pipes we have open.
127     brillo::ProcessImpl proc;
128 
129     // These are used to monitor the stdout of the running process, including
130     // the stderr if it was redirected.
131     std::unique_ptr<base::FileDescriptorWatcher::Controller> stdout_controller;
132 
133     int stdout_fd{-1};
134     std::string stdout_str;
135   };
136 
137   // Callback which runs whenever there is input available on the subprocess
138   // stdout pipe.
139   static void OnStdoutReady(SubprocessRecord* record);
140 
141   // Callback for when any subprocess terminates. This calls the user
142   // requested callback.
143   void ChildExitedCallback(const siginfo_t& info);
144 
145   // The global instance.
146   static Subprocess* subprocess_singleton_;
147 
148   // A map from the asynchronous subprocess tag (see Exec) to the subprocess
149   // record structure for all active asynchronous subprocesses.
150   std::map<pid_t, std::unique_ptr<SubprocessRecord>> subprocess_records_;
151 
152   // Used to watch for child processes.
153   brillo::ProcessReaper process_reaper_;
154 
155   DISALLOW_COPY_AND_ASSIGN(Subprocess);
156 };
157 
158 }  // namespace chromeos_update_engine
159 
160 #endif  // UPDATE_ENGINE_COMMON_SUBPROCESS_H_
161