| Index: chromeos/process_proxy/process_proxy.cc
|
| diff --git a/chromeos/process_proxy/process_proxy.cc b/chromeos/process_proxy/process_proxy.cc
|
| index 4907d8bca5c663a7e76b190bb09ecc9233b07e9d..8ec9cebabcf991584ac03ad668bfc210b604a19e 100644
|
| --- a/chromeos/process_proxy/process_proxy.cc
|
| +++ b/chromeos/process_proxy/process_proxy.cc
|
| @@ -17,16 +17,10 @@
|
| #include "base/process/process.h"
|
| #include "base/single_thread_task_runner.h"
|
| #include "base/thread_task_runner_handle.h"
|
| -#include "base/threading/thread.h"
|
| #include "third_party/cros_system_api/switches/chrome_switches.h"
|
|
|
| namespace {
|
|
|
| -enum PipeEnd {
|
| - PIPE_END_READ,
|
| - PIPE_END_WRITE
|
| -};
|
| -
|
| enum PseudoTerminalFd {
|
| PT_MASTER_FD,
|
| PT_SLAVE_FD
|
| @@ -34,16 +28,18 @@ enum PseudoTerminalFd {
|
|
|
| const int kInvalidFd = -1;
|
|
|
| +void StopOutputWatcher(scoped_ptr<chromeos::ProcessOutputWatcher> watcher) {
|
| + // Just deleting |watcher| if sufficient to stop it.
|
| +}
|
| +
|
| } // namespace
|
|
|
| namespace chromeos {
|
|
|
| -ProcessProxy::ProcessProxy(): process_launched_(false),
|
| - callback_set_(false),
|
| - watcher_started_(false) {
|
| +ProcessProxy::ProcessProxy() : process_launched_(false), callback_set_(false) {
|
| // Set pipes to initial, invalid value so we can easily know if a pipe was
|
| // opened by us.
|
| - ClearAllFdPairs();
|
| + ClearFdPair(pt_pair_);
|
| }
|
|
|
| bool ProcessProxy::Open(const std::string& command, pid_t* pid) {
|
| @@ -67,45 +63,33 @@ bool ProcessProxy::Open(const std::string& command, pid_t* pid) {
|
| return process_launched_;
|
| }
|
|
|
| -bool ProcessProxy::StartWatchingOnThread(
|
| - base::Thread* watch_thread,
|
| +bool ProcessProxy::StartWatchingOutput(
|
| + const scoped_refptr<base::SingleThreadTaskRunner>& watcher_runner,
|
| const ProcessOutputCallback& callback) {
|
| DCHECK(process_launched_);
|
| - if (watcher_started_)
|
| - return false;
|
| - if (pipe(shutdown_pipe_) ||
|
| - !ProcessOutputWatcher::VerifyFileDescriptor(
|
| - shutdown_pipe_[PIPE_END_READ])) {
|
| - return false;
|
| - }
|
| + CHECK(!output_watcher_.get());
|
|
|
| // We give ProcessOutputWatcher a copy of master to make life easier during
|
| // tear down.
|
| // TODO(tbarzic): improve fd managment.
|
| int master_copy = HANDLE_EINTR(dup(pt_pair_[PT_MASTER_FD]));
|
| - if (!ProcessOutputWatcher::VerifyFileDescriptor(master_copy))
|
| + if (master_copy < 0)
|
| return false;
|
|
|
| callback_set_ = true;
|
| callback_ = callback;
|
| callback_runner_ = base::ThreadTaskRunnerHandle::Get();
|
| + watcher_runner_ = watcher_runner;
|
|
|
| // This object will delete itself once watching is stopped.
|
| // It also takes ownership of the passed fds.
|
| - ProcessOutputWatcher* output_watcher =
|
| - new ProcessOutputWatcher(master_copy,
|
| - shutdown_pipe_[PIPE_END_READ],
|
| - base::Bind(&ProcessProxy::OnProcessOutput,
|
| - this));
|
| -
|
| - // Output watcher took ownership of the read end of shutdown pipe.
|
| - shutdown_pipe_[PIPE_END_READ] = -1;
|
| + output_watcher_.reset(new ProcessOutputWatcher(
|
| + master_copy, base::Bind(&ProcessProxy::OnProcessOutput, this)));
|
|
|
| - // |watch| thread is blocked by |output_watcher| from now on.
|
| - watch_thread->task_runner()->PostTask(
|
| + watcher_runner_->PostTask(
|
| FROM_HERE, base::Bind(&ProcessOutputWatcher::Start,
|
| - base::Unretained(output_watcher)));
|
| - watcher_started_ = true;
|
| + base::Unretained(output_watcher_.get())));
|
| +
|
| return true;
|
| }
|
|
|
| @@ -131,14 +115,13 @@ void ProcessProxy::CallOnProcessOutputCallback(ProcessOutputType type,
|
| callback_.Run(type, output);
|
| }
|
|
|
| -bool ProcessProxy::StopWatching() {
|
| - if (!watcher_started_)
|
| - return true;
|
| - // Signal Watcher that we are done. We use self-pipe trick to unblock watcher.
|
| - // Anything may be written to the pipe.
|
| - const char message[] = "q";
|
| - return base::WriteFileDescriptor(shutdown_pipe_[PIPE_END_WRITE],
|
| - message, sizeof(message));
|
| +void ProcessProxy::StopWatching() {
|
| + if (!output_watcher_.get())
|
| + return;
|
| +
|
| + watcher_runner_->PostTask(
|
| + FROM_HERE,
|
| + base::Bind(&StopOutputWatcher, base::Passed(&output_watcher_)));
|
| }
|
|
|
| void ProcessProxy::Close() {
|
| @@ -153,10 +136,8 @@ void ProcessProxy::Close() {
|
| base::Process process = base::Process::DeprecatedGetProcessFromHandle(pid_);
|
| process.Terminate(0, true /* wait */);
|
|
|
| - // TODO(tbarzic): What if this fails?
|
| StopWatching();
|
| -
|
| - CloseAllFdPairs();
|
| + CloseFdPair(pt_pair_);
|
| }
|
|
|
| bool ProcessProxy::Write(const std::string& text) {
|
| @@ -183,13 +164,7 @@ bool ProcessProxy::OnTerminalResize(int width, int height) {
|
| }
|
|
|
| ProcessProxy::~ProcessProxy() {
|
| - // In case watcher did not started, we may get deleted without calling Close.
|
| - // In that case we have to clean up created pipes. If watcher had been
|
| - // started, there will be a callback with our reference owned by
|
| - // process_output_watcher until Close is called, so we know Close has been
|
| - // called by now (and pipes have been cleaned).
|
| - if (!watcher_started_)
|
| - CloseAllFdPairs();
|
| + Close();
|
| }
|
|
|
| bool ProcessProxy::CreatePseudoTerminalPair(int *pt_pair) {
|
| @@ -246,14 +221,9 @@ bool ProcessProxy::LaunchProcess(const std::string& command, int slave_fd,
|
| return process.IsValid();
|
| }
|
|
|
| -void ProcessProxy::CloseAllFdPairs() {
|
| - CloseFdPair(pt_pair_);
|
| - CloseFdPair(shutdown_pipe_);
|
| -}
|
| -
|
| void ProcessProxy::CloseFdPair(int* pipe) {
|
| - CloseFd(&(pipe[PIPE_END_READ]));
|
| - CloseFd(&(pipe[PIPE_END_WRITE]));
|
| + CloseFd(&(pipe[PT_MASTER_FD]));
|
| + CloseFd(&(pipe[PT_SLAVE_FD]));
|
| }
|
|
|
| void ProcessProxy::CloseFd(int* fd) {
|
| @@ -264,14 +234,9 @@ void ProcessProxy::CloseFd(int* fd) {
|
| *fd = kInvalidFd;
|
| }
|
|
|
| -void ProcessProxy::ClearAllFdPairs() {
|
| - ClearFdPair(pt_pair_);
|
| - ClearFdPair(shutdown_pipe_);
|
| -}
|
| -
|
| void ProcessProxy::ClearFdPair(int* pipe) {
|
| - pipe[PIPE_END_READ] = kInvalidFd;
|
| - pipe[PIPE_END_WRITE] = kInvalidFd;
|
| + pipe[PT_MASTER_FD] = kInvalidFd;
|
| + pipe[PT_SLAVE_FD] = kInvalidFd;
|
| }
|
|
|
| } // namespace chromeos
|
|
|