OLD | NEW |
(Empty) | |
| 1 // Copyright 2015 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 "services/native_support/process_controller_impl.h" |
| 6 |
| 7 #include <errno.h> |
| 8 #include <signal.h> |
| 9 #include <sys/types.h> |
| 10 |
| 11 #include <utility> |
| 12 |
| 13 #include "base/bind.h" |
| 14 #include "base/callback.h" |
| 15 #include "base/location.h" |
| 16 #include "base/logging.h" |
| 17 #include "base/message_loop/message_loop.h" |
| 18 #include "base/task_runner.h" |
| 19 #include "base/threading/simple_thread.h" |
| 20 #include "mojo/services/files/public/interfaces/types.mojom.h" |
| 21 #include "services/native_support/process_io_redirection.h" |
| 22 |
| 23 namespace native_support { |
| 24 |
| 25 namespace { |
| 26 |
| 27 void WaitForProcess( |
| 28 base::Process process, |
| 29 scoped_refptr<base::TaskRunner> done_runner, |
| 30 const base::Callback<void(mojo::files::Error, int32_t)>& done_callback) { |
| 31 int exit_status = 0; |
| 32 mojo::files::Error result = process.WaitForExit(&exit_status) |
| 33 ? mojo::files::ERROR_OK |
| 34 : mojo::files::ERROR_UNKNOWN; |
| 35 done_runner->PostTask( |
| 36 FROM_HERE, |
| 37 base::Bind(done_callback, result, static_cast<int32_t>(exit_status))); |
| 38 } |
| 39 |
| 40 void TerminateProcess(base::Process process) { |
| 41 if (!process.Terminate(-1, true)) |
| 42 LOG(ERROR) << "Failed to kill PID " << process.Pid(); |
| 43 } |
| 44 |
| 45 } // namespace |
| 46 |
| 47 ProcessControllerImpl::ProcessControllerImpl( |
| 48 scoped_refptr<base::TaskRunner> worker_runner, |
| 49 mojo::InterfaceRequest<ProcessController> request, |
| 50 base::Process process, |
| 51 std::unique_ptr<ProcessIORedirection> process_io_redirection) |
| 52 : worker_runner_(worker_runner.Pass()), |
| 53 binding_(this, request.Pass()), |
| 54 process_(process.Pass()), |
| 55 process_io_redirection_(std::move(process_io_redirection)), |
| 56 weak_factory_(this) { |
| 57 DCHECK(process_.IsValid()); |
| 58 } |
| 59 |
| 60 ProcessControllerImpl::~ProcessControllerImpl() { |
| 61 if (process_.IsValid()) { |
| 62 worker_runner_->PostTask( |
| 63 FROM_HERE, base::Bind(&TerminateProcess, base::Passed(&process_))); |
| 64 } |
| 65 } |
| 66 |
| 67 void ProcessControllerImpl::Wait(const WaitCallback& callback) { |
| 68 if (!process_.IsValid()) { |
| 69 // TODO(vtl): This isn't quite right. |
| 70 callback.Run(mojo::files::ERROR_UNAVAILABLE, 0); |
| 71 return; |
| 72 } |
| 73 |
| 74 worker_runner_->PostTask( |
| 75 FROM_HERE, base::Bind(&WaitForProcess, base::Passed(&process_), |
| 76 base::MessageLoop::current()->task_runner(), |
| 77 base::Bind(&ProcessControllerImpl::OnWaitComplete, |
| 78 weak_factory_.GetWeakPtr(), callback))); |
| 79 } |
| 80 |
| 81 void ProcessControllerImpl::Kill(int32_t signal, const KillCallback& callback) { |
| 82 callback.Run(KillHelper(signal)); |
| 83 } |
| 84 |
| 85 void ProcessControllerImpl::OnWaitComplete(const WaitCallback& callback, |
| 86 mojo::files::Error result, |
| 87 int32_t exit_status) { |
| 88 callback.Run(result, exit_status); |
| 89 } |
| 90 |
| 91 mojo::files::Error ProcessControllerImpl::KillHelper(int32_t signal) { |
| 92 if (signal < 0) |
| 93 return mojo::files::ERROR_INVALID_ARGUMENT; |
| 94 |
| 95 if (!process_.IsValid()) { |
| 96 LOG(ERROR) << "Kill() called after Wait()"; |
| 97 // TODO(vtl): This error code isn't quite right, but "unavailable" (which |
| 98 // would also be wrong) is used for a more appropriate purpose below. |
| 99 return mojo::files::ERROR_INVALID_ARGUMENT; |
| 100 } |
| 101 |
| 102 // |base::HandleType| is just a typedef for |pid_t|. |
| 103 pid_t pid = process_.Handle(); |
| 104 |
| 105 // Note: |kill()| is not interruptible. |
| 106 if (kill(pid, static_cast<int>(signal)) == 0) |
| 107 return mojo::files::ERROR_OK; |
| 108 |
| 109 switch (errno) { |
| 110 case EINVAL: |
| 111 return mojo::files::ERROR_INVALID_ARGUMENT; |
| 112 case EPERM: |
| 113 return mojo::files::ERROR_PERMISSION_DENIED; |
| 114 case ESRCH: |
| 115 return mojo::files::ERROR_UNAVAILABLE; |
| 116 default: |
| 117 break; |
| 118 } |
| 119 return mojo::files::ERROR_UNKNOWN; |
| 120 } |
| 121 |
| 122 } // namespace native_support |
OLD | NEW |