1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "sandbox/linux/services/init_process_reaper.h"
9 #include <sys/socket.h>
10 #include <sys/types.h>
14 #include "base/callback.h"
15 #include "base/logging.h"
16 #include "base/posix/eintr_wrapper.h"
22 void DoNothingSignalHandler(int signal
) {}
26 bool CreateInitProcessReaper(base::Closure
* post_fork_parent_callback
) {
28 // We want to use send, so we can't use a pipe
29 if (socketpair(AF_UNIX
, SOCK_STREAM
, 0, sync_fds
)) {
30 PLOG(ERROR
) << "Failed to create socketpair";
33 pid_t child_pid
= fork();
34 if (child_pid
== -1) {
36 close_ret
= IGNORE_EINTR(close(sync_fds
[0]));
38 close_ret
= IGNORE_EINTR(close(sync_fds
[1]));
43 // In the parent, assuming the role of an init process.
44 // The disposition for SIGCHLD cannot be SIG_IGN or wait() will only return
45 // once all of our childs are dead. Since we're init we need to reap childs
47 struct sigaction action
;
48 memset(&action
, 0, sizeof(action
));
49 action
.sa_handler
= &DoNothingSignalHandler
;
50 CHECK(sigaction(SIGCHLD
, &action
, NULL
) == 0);
53 close_ret
= IGNORE_EINTR(close(sync_fds
[0]));
55 close_ret
= shutdown(sync_fds
[1], SHUT_RD
);
57 if (post_fork_parent_callback
)
58 post_fork_parent_callback
->Run();
59 // Tell the child to continue
60 CHECK(HANDLE_EINTR(send(sync_fds
[1], "C", 1, MSG_NOSIGNAL
)) == 1);
61 close_ret
= IGNORE_EINTR(close(sync_fds
[1]));
65 // Loop until we have reaped our one natural child
66 siginfo_t reaped_child_info
;
68 HANDLE_EINTR(waitid(P_ALL
, 0, &reaped_child_info
, WEXITED
));
71 if (reaped_child_info
.si_pid
== child_pid
) {
74 if (reaped_child_info
.si_code
== CLD_EXITED
) {
75 exit_code
= reaped_child_info
.si_status
;
77 // Exit with the same exit code as our parent. Exit with 0 if we got
83 // The child needs to wait for the parent to run the callback to avoid a
86 close_ret
= IGNORE_EINTR(close(sync_fds
[1]));
88 close_ret
= shutdown(sync_fds
[0], SHUT_WR
);
91 int read_ret
= HANDLE_EINTR(read(sync_fds
[0], &should_continue
, 1));
92 close_ret
= IGNORE_EINTR(close(sync_fds
[0]));
101 } // namespace sandbox.