| Index: base/win/process_monitor.cc
|
| diff --git a/base/win/process_monitor.cc b/base/win/process_monitor.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..3da28e2c1de0e4dd51fd891891f654a64adda5d0
|
| --- /dev/null
|
| +++ b/base/win/process_monitor.cc
|
| @@ -0,0 +1,103 @@
|
| +// Copyright (c) 2011 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#include "base/win/process_monitor.h"
|
| +
|
| +#include "base/location.h"
|
| +#include "base/logging.h"
|
| +#include "base/message_loop_proxy.h"
|
| +
|
| +namespace base {
|
| +namespace win {
|
| +
|
| +ProcessMonitor::ProcessMonitor() : monitoring_job_completion_port_(NULL),
|
| + stop_job_monitoring_(false),
|
| + monitoring_job_(NULL) {
|
| +}
|
| +
|
| +ProcessMonitor::~ProcessMonitor() {
|
| + Stop();
|
| + if (monitoring_job_) {
|
| + ::CloseHandle(monitoring_job_);
|
| + monitoring_job_ = NULL;
|
| + }
|
| +}
|
| +
|
| +void ProcessMonitor::Initialize(HANDLE process_handle,
|
| + const Closure& callback) {
|
| + DCHECK(monitoring_job_ == NULL);
|
| +
|
| + monitoring_job_ = ::CreateJobObject(NULL, NULL);
|
| + if (monitoring_job_ == NULL) {
|
| + DPLOG(FATAL) << "Failed to create process monitoring job: ";
|
| + return;
|
| + }
|
| +
|
| + if (!PlatformThread::Create(0, this, &thread_)) {
|
| + NOTREACHED();
|
| + return;
|
| + }
|
| +
|
| + callback_ = callback;
|
| + callback_message_loop_ = MessageLoopProxy::current();
|
| + if (!AssignProcessToJobObject(monitoring_job_, process_handle)) {
|
| + DPLOG(FATAL) << "Couldn't assign process to job: ";
|
| + }
|
| +}
|
| +
|
| +void ProcessMonitor::ThreadMain() {
|
| + PlatformThread::SetName("Process monitor thread");
|
| +
|
| + if (!monitoring_job_) {
|
| + DLOG(FATAL) << "Invalid job information";
|
| + return;
|
| + }
|
| +
|
| + DCHECK(monitoring_job_completion_port_ == NULL);
|
| +
|
| + monitoring_job_completion_port_ =
|
| + ::CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL,
|
| + reinterpret_cast<ULONG_PTR>(monitoring_job_), 0);
|
| + DCHECK(monitoring_job_completion_port_ != NULL);
|
| +
|
| + JOBOBJECT_ASSOCIATE_COMPLETION_PORT job_completion_port = {0};
|
| + job_completion_port.CompletionKey = monitoring_job_;
|
| + job_completion_port.CompletionPort = monitoring_job_completion_port_;
|
| +
|
| + if (!SetInformationJobObject(monitoring_job_,
|
| + JobObjectAssociateCompletionPortInformation,
|
| + &job_completion_port,
|
| + sizeof(job_completion_port))) {
|
| + DPLOG(FATAL) << "Failed to associate completion port with job object: ";
|
| + return;
|
| + }
|
| +
|
| + while (!stop_job_monitoring_) {
|
| + unsigned long job_event = 0;
|
| + ULONG_PTR completion_key = 0;
|
| + LPOVERLAPPED overlapped = NULL;
|
| +
|
| + if (::GetQueuedCompletionStatus(
|
| + monitoring_job_completion_port_, &job_event,
|
| + &completion_key, &overlapped, INFINITE)) {
|
| + if (job_event == JOB_OBJECT_MSG_ACTIVE_PROCESS_ZERO) {
|
| + DVLOG(1) << "All processes in the monitoring job have exited.";
|
| + callback_message_loop_->PostTask(FROM_HERE, callback_);
|
| + }
|
| + }
|
| + }
|
| +}
|
| +
|
| +void ProcessMonitor::Stop() {
|
| + stop_job_monitoring_ = true;
|
| + ::PostQueuedCompletionStatus(
|
| + monitoring_job_completion_port_, JOB_OBJECT_MSG_END_OF_JOB_TIME,
|
| + reinterpret_cast<ULONG_PTR>(monitoring_job_), NULL);
|
| + PlatformThread::Join(thread_);
|
| + ::CloseHandle(monitoring_job_completion_port_);
|
| + monitoring_job_completion_port_ = NULL;
|
| +}
|
| +
|
| +} // namespace win
|
| +} // namespace base
|
|
|