ad1657174e6f84baeb1f946c40636ff042d17768
[iec.git] / src / type3_AndroidCloud / anbox-master / external / process-cpp-minimal / src / core / posix / child_process.cpp
1 /*
2  * Copyright © 2013 Canonical Ltd.
3  *
4  * This program is free software: you can redistribute it and/or modify it
5  * under the terms of the GNU Lesser General Public License version 3,
6  * as published by the Free Software Foundation.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11  * GNU Lesser General Public License for more details.
12  *
13  * You should have received a copy of the GNU Lesser General Public License
14  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
15  *
16  * Authored by: Thomas Voß <thomas.voss@canonical.com>
17  */
18
19 #include <core/posix/child_process.h>
20
21 #ifndef ANDROID
22 #include <boost/iostreams/device/file_descriptor.hpp>
23 #include <boost/iostreams/stream.hpp>
24 #endif
25
26 #include <atomic>
27 #include <fstream>
28 #include <mutex>
29 #include <unordered_map>
30
31 #include <fcntl.h>
32 #include <poll.h>
33 #include <unistd.h>
34
35 #include <sys/eventfd.h>
36 #include <sys/signalfd.h>
37
38 #include <assert.h>
39
40 #include <sys/wait.h>
41
42 #ifndef ANDROID
43 namespace io = boost::iostreams;
44 #endif
45
46 namespace
47 {
48
49 struct DeathObserverImpl : public core::posix::ChildProcess::DeathObserver
50 {
51     DeathObserverImpl(const std::shared_ptr<core::posix::SignalTrap>& trap)
52         : on_sig_child_connection
53           {
54               trap->signal_raised().connect([this](core::posix::Signal signal)
55               {
56                   switch (signal)
57                   {
58                   case core::posix::Signal::sig_chld:
59                     on_sig_child();
60                     break;
61                   default:
62                     break;
63                   }
64               })
65           }
66     {
67         if (!trap->has(core::posix::Signal::sig_chld))
68             throw std::logic_error(
69                     "DeathObserver::DeathObserverImpl: Given SignalTrap"
70                     " instance does not trap Signal::sig_chld.");
71     }
72
73     bool add(const core::posix::ChildProcess& process) override
74     {
75         if (process.pid() == -1)
76             return false;
77
78         std::lock_guard<std::mutex> lg(guard);
79
80         bool added = false;
81         auto new_process = std::make_pair(process.pid(), process);
82         std::tie(std::ignore, added) = children.insert(new_process);
83
84         if (added)
85         {
86             // The process may have died between it's instantiation and it
87             // being added to the children map. Check that it's still alive.
88             int status{-1};
89             if (::waitpid(process.pid(), &status, WNOHANG) != 0) // child no longer alive
90             {
91                 // we missed the SIGCHLD signal so we must now manually
92                 // inform our subscribers.
93                 signals.child_died(new_process.second);
94                 children.erase(new_process.first);
95                 return false;
96             }
97         }
98
99         return added;
100     }
101
102     bool has(const core::posix::ChildProcess& process) const override
103     {
104         std::lock_guard<std::mutex> lg(guard);
105         return children.count(process.pid()) > 0;
106     }
107
108     const core::Signal<core::posix::ChildProcess>& child_died() const override
109     {
110         return signals.child_died;
111     }
112
113     void on_sig_child() override
114     {
115         pid_t pid{-1}; int status{-1};
116         while (true)
117         {
118             pid = ::waitpid(0, &status, WNOHANG);
119
120             if (pid == -1)
121             {
122                 if (errno == ECHILD)
123                 {
124                     break; // No more children
125                 }
126                 continue; // Ignore stray SIGCHLD signals
127             }
128             else if (pid == 0)
129             {
130                 break; // No more children
131             }
132             else
133             {
134                 std::lock_guard<std::mutex> lg(guard);
135                 auto it = children.find(pid);
136
137                 if (it != children.end())
138                 {
139                     if (WIFSIGNALED(status) || WIFEXITED(status))
140                     {
141                         signals.child_died(it->second);
142                         children.erase(it);
143                     }
144                 }
145             }
146         }
147     }
148
149     mutable std::mutex guard;
150     std::unordered_map<pid_t, core::posix::ChildProcess> children;
151     core::ScopedConnection on_sig_child_connection;
152     struct
153     {
154         core::Signal<core::posix::ChildProcess> child_died;
155     } signals;
156 };
157 }
158
159 std::unique_ptr<core::posix::ChildProcess::DeathObserver>
160 core::posix::ChildProcess::DeathObserver::create_once_with_signal_trap(
161         std::shared_ptr<core::posix::SignalTrap> trap)
162 {
163     static std::atomic<bool> has_been_created_once{false};
164
165     if (has_been_created_once.exchange(true))
166         throw std::runtime_error
167         {
168             "DeathObserver::create_once_with_signal_trap: "
169             "Cannot create more than one instance."
170         };
171
172     try
173     {
174         std::unique_ptr<core::posix::ChildProcess::DeathObserver> result
175         {
176             new DeathObserverImpl{trap}
177         };
178
179         return result;
180     } catch(...)
181     {
182         // We make sure that a throwing c'tor does not impact our ability to
183         // retry creation of a DeathObserver instance.
184         has_been_created_once.store(false);
185
186         std::rethrow_exception(std::current_exception());
187     }
188
189     assert(false && "We should never reach here.");
190
191     // Silence the compiler.
192     return std::unique_ptr<core::posix::ChildProcess::DeathObserver>{};
193 }
194
195 namespace core
196 {
197 namespace posix
198 {
199 ChildProcess::Pipe ChildProcess::Pipe::invalid()
200 {
201     static Pipe p;
202     static std::once_flag flag;
203
204     std::call_once(flag, [&]() { p.close_read_fd(); p.close_write_fd(); });
205
206     return p;
207 }
208
209 ChildProcess::Pipe::Pipe()
210 {
211     int rc = ::pipe(fds);
212
213     if (rc == -1)
214         throw std::system_error(errno, std::system_category());
215 }
216
217 ChildProcess::Pipe::Pipe(const ChildProcess::Pipe& rhs) : fds{-1, -1}
218 {
219     if (rhs.fds[0] != -1)
220         fds[0] = ::dup(rhs.fds[0]);
221
222     if (rhs.fds[1] != -1)
223         fds[1] = ::dup(rhs.fds[1]);
224 }
225
226 ChildProcess::Pipe::~Pipe()
227 {
228     if (fds[0] != -1)
229         ::close(fds[0]);
230     if (fds[1] != -1)
231         ::close(fds[1]);
232 }
233
234 int ChildProcess::Pipe::read_fd() const
235 {
236     return fds[0];
237 }
238
239 void ChildProcess::Pipe::close_read_fd()
240 {
241     if (fds[0] != -1)
242     {
243         ::close(fds[0]);
244         fds[0] = -1;
245     }
246 }
247
248 int ChildProcess::Pipe::write_fd() const
249 {
250     return fds[1];
251 }
252
253 void ChildProcess::Pipe::close_write_fd()
254 {
255     if (fds[1] != -1)
256     {
257         ::close(fds[1]);
258         fds[1] = -1;
259     }
260 }
261
262 ChildProcess::Pipe& ChildProcess::Pipe::operator=(const ChildProcess::Pipe& rhs)
263 {
264     if (fds[0] != -1)
265         ::close(fds[0]);
266     if (fds[1] != -1)
267         ::close(fds[1]);
268
269     if (rhs.fds[0] != -1)
270         fds[0] = ::dup(rhs.fds[0]);
271     else
272         fds[0] = -1;
273     if (rhs.fds[1] != -1)
274         fds[1] = ::dup(rhs.fds[1]);
275     else
276         fds[1] = -1;
277
278     return *this;
279 }
280
281 struct ChildProcess::Private
282 {
283     // stdin and stdout are always "relative" to the childprocess, i.e., we
284     // write to stdin of the child process and read from its stdout.
285     Private(pid_t pid,
286             const ChildProcess::Pipe& stderr,
287             const ChildProcess::Pipe& stdin,
288             const ChildProcess::Pipe& stdout)
289         : pipes{stderr, stdin, stdout},
290 #ifndef ANDROID
291           serr(pipes.stderr.read_fd(), io::never_close_handle),
292           sin(pipes.stdin.write_fd(), io::never_close_handle),
293           sout(pipes.stdout.read_fd(), io::never_close_handle),
294           cerr(&serr),
295           cin(&sin),
296           cout(&sout),
297 #endif
298           original_parent_pid(::getpid()),
299           original_child_pid(pid)
300     {
301     }
302
303     ~Private()
304     {
305         // Check if we are in the original parent process.
306         if (original_parent_pid == getpid() && !dont_kill_on_cleanup)
307         {
308             // If so, check if we are considering a valid pid here.
309             // If so, we kill the original child.
310             if (original_child_pid != -1)
311                 ::kill(original_child_pid, SIGKILL);
312         }
313     }
314
315     struct
316     {
317         ChildProcess::Pipe stdin;
318         ChildProcess::Pipe stdout;
319         ChildProcess::Pipe stderr;
320     } pipes;
321
322 #ifndef ANDROID
323     io::stream_buffer<io::file_descriptor_source> serr;
324     io::stream_buffer<io::file_descriptor_sink> sin;
325     io::stream_buffer<io::file_descriptor_source> sout;
326     std::istream cerr;
327     std::ostream cin;
328     std::istream cout;
329 #endif
330
331     // We need to store the original parent pid as we might have been forked
332     // and with our automatic cleanup in place, it might happen that the d'tor
333     // is called from the child process.
334     pid_t original_parent_pid;
335     pid_t original_child_pid;
336
337     bool dont_kill_on_cleanup = false;
338 };
339
340 ChildProcess ChildProcess::invalid()
341 {
342     // We take the init process as child.
343     static const pid_t invalid_pid = 1;
344     return ChildProcess(invalid_pid, Pipe::invalid(), Pipe::invalid(), Pipe::invalid());
345 }
346
347 ChildProcess::ChildProcess(pid_t pid,
348                            const ChildProcess::Pipe& stdin_pipe,
349                            const ChildProcess::Pipe& stdout_pipe,
350                            const ChildProcess::Pipe& stderr_pipe)
351     : Process(pid),
352       d(new Private{pid, stdin_pipe, stdout_pipe, stderr_pipe})
353 {
354 }
355
356 ChildProcess::~ChildProcess()
357 {
358 }
359
360 wait::Result ChildProcess::wait_for(const wait::Flags& flags)
361 {
362     int status = -1;
363     pid_t result_pid = ::waitpid(pid(), std::addressof(status), static_cast<int>(flags));
364
365     if (result_pid == -1)
366         throw std::system_error(errno, std::system_category());
367
368     wait::Result result;
369
370     if (result_pid == 0)
371     {
372         result.status = wait::Result::Status::no_state_change;
373         return result;
374     }
375
376     if (WIFEXITED(status))
377     {
378         result.status = wait::Result::Status::exited;
379         result.detail.if_exited.status = static_cast<exit::Status>(WEXITSTATUS(status));
380     } else if (WIFSIGNALED(status))
381     {
382         result.status = wait::Result::Status::signaled;
383         result.detail.if_signaled.signal = static_cast<Signal>(WTERMSIG(status));
384         result.detail.if_signaled.core_dumped = WCOREDUMP(status);
385     } else if (WIFSTOPPED(status))
386     {
387         result.status = wait::Result::Status::stopped;
388         result.detail.if_stopped.signal = static_cast<Signal>(WSTOPSIG(status));
389     }
390 #ifndef ANDROID
391     else if (WIFCONTINUED(status))
392     {
393         result.status = wait::Result::Status::continued;
394     }
395 #endif
396
397     return result;
398 }
399
400 void ChildProcess::dont_kill_on_cleanup()
401 {
402   d->dont_kill_on_cleanup = true;
403 }
404
405 #ifndef ANDROID
406 std::istream& ChildProcess::cerr()
407 {
408     return d->cerr;
409 }
410
411 std::ostream& ChildProcess::cin()
412 {
413     return d->cin;
414 }
415
416 std::istream& ChildProcess::cout()
417 {
418     return d->cout;
419 }
420 #endif
421 }
422 }