OLD | NEW |
(Empty) | |
| 1 // Copyright 2014 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. |
| 4 |
| 5 #include "sandbox/linux/services/scoped_process.h" |
| 6 |
| 7 #include <fcntl.h> |
| 8 #include <signal.h> |
| 9 #include <sys/stat.h> |
| 10 #include <sys/syscall.h> |
| 11 #include <sys/types.h> |
| 12 #include <sys/wait.h> |
| 13 #include <unistd.h> |
| 14 |
| 15 #include "base/basictypes.h" |
| 16 #include "base/logging.h" |
| 17 #include "base/posix/eintr_wrapper.h" |
| 18 #include "sandbox/linux/services/thread_helpers.h" |
| 19 |
| 20 namespace sandbox { |
| 21 |
| 22 ScopedProcess::ScopedProcess(const base::Closure& child_callback) |
| 23 : child_callback_(child_callback), |
| 24 child_process_id_(-1), |
| 25 process_id_(getpid()) { |
| 26 // Make sure that we can safely fork(). |
| 27 CHECK(ThreadHelpers::IsSingleThreaded(-1)); |
| 28 child_process_id_ = fork(); |
| 29 PCHECK(0 <= child_process_id_); |
| 30 if (0 == child_process_id_) { |
| 31 child_callback_.Run(); |
| 32 _exit(0); |
| 33 } |
| 34 } |
| 35 |
| 36 ScopedProcess::~ScopedProcess() { |
| 37 CHECK(IsOriginalProcess()); |
| 38 if (child_process_id_ >= 0) { |
| 39 PCHECK(0 == kill(child_process_id_, SIGKILL)); |
| 40 siginfo_t process_info; |
| 41 |
| 42 PCHECK(0 == HANDLE_EINTR( |
| 43 waitid(P_PID, child_process_id_, &process_info, WEXITED))); |
| 44 } |
| 45 } |
| 46 |
| 47 int ScopedProcess::WaitForExit(bool* got_signaled) { |
| 48 DCHECK(got_signaled); |
| 49 CHECK(IsOriginalProcess()); |
| 50 siginfo_t process_info; |
| 51 // WNOWAIT to make sure that the destructor can wait on the child. |
| 52 int ret = HANDLE_EINTR( |
| 53 waitid(P_PID, child_process_id_, &process_info, WEXITED | WNOWAIT)); |
| 54 PCHECK(0 == ret) << "Did something else wait on the child?"; |
| 55 |
| 56 if (process_info.si_code == CLD_EXITED) { |
| 57 *got_signaled = false; |
| 58 } else if (process_info.si_code == CLD_KILLED || |
| 59 process_info.si_code == CLD_DUMPED) { |
| 60 *got_signaled = true; |
| 61 } else { |
| 62 CHECK(false) << "ScopedProcess needs to be extended for si_code " |
| 63 << process_info.si_code; |
| 64 } |
| 65 return process_info.si_status; |
| 66 } |
| 67 |
| 68 // It would be problematic if after a fork(), another process would start using |
| 69 // this object. |
| 70 // This method allows to assert it is not happening. |
| 71 bool ScopedProcess::IsOriginalProcess() { |
| 72 // Make a direct syscall to bypass glibc caching of PIDs. |
| 73 int pid = syscall(__NR_getpid); |
| 74 return pid == process_id_; |
| 75 } |
| 76 |
| 77 } // namespace sandbox |
OLD | NEW |