Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2242)

Unified Diff: base/win/scoped_process_information.cc

Issue 9700038: ScopedProcessInformation protects against process/thread handle leaks from CreateProcess calls. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Add tests for new functions. Created 8 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « base/win/scoped_process_information.h ('k') | base/win/scoped_process_information_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: base/win/scoped_process_information.cc
diff --git a/base/win/scoped_process_information.cc b/base/win/scoped_process_information.cc
new file mode 100644
index 0000000000000000000000000000000000000000..615e901f10cecf053d1a8ac177c3d7735c883b95
--- /dev/null
+++ b/base/win/scoped_process_information.cc
@@ -0,0 +1,126 @@
+// Copyright (c) 2012 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/scoped_process_information.h"
+
+#include "base/logging.h"
+#include "base/win/scoped_handle.h"
+
+namespace base {
+namespace win {
+
+namespace {
+
+// Closes the provided handle if it is not NULL.
+void CheckAndCloseHandle(HANDLE handle) {
+ if (!handle)
+ return;
+ if (::CloseHandle(handle))
+ return;
+ DPCHECK(false) << "Failed to close a handle.";
+}
+
+// Duplicates source into target, returning true upon success. |target| is
+// guaranteed to be untouched in case of failure. Succeeds with no side-effects
+// if source is NULL.
+bool CheckAndDuplicateHandle(HANDLE source, HANDLE* target) {
+ if (!source)
+ return true;
+
+ HANDLE temp = NULL;
+ if (!::DuplicateHandle(::GetCurrentProcess(), source,
+ ::GetCurrentProcess(), &temp, 0, FALSE,
+ DUPLICATE_SAME_ACCESS)) {
+ DPLOG(ERROR) << "Failed to duplicate a handle.";
+ return false;
+ }
+ *target = temp;
+ return true;
+}
+
+} // namespace
+
+ScopedProcessInformation::ScopedProcessInformation()
+ : process_information_() {
+}
+
+ScopedProcessInformation::~ScopedProcessInformation() {
+ Close();
+}
+
+PROCESS_INFORMATION* ScopedProcessInformation::Receive() {
+ DCHECK(!IsValid()) << "process_information_ must be NULL";
+ return &process_information_;
+}
+
+bool ScopedProcessInformation::IsValid() const {
+ return process_information_.hThread || process_information_.hProcess ||
+ process_information_.dwProcessId || process_information_.dwThreadId;
+}
+
+
+void ScopedProcessInformation::Close() {
+ CheckAndCloseHandle(process_information_.hThread);
+ CheckAndCloseHandle(process_information_.hProcess);
+ Reset();
+}
+
+void ScopedProcessInformation::Swap(ScopedProcessInformation* other) {
brettw 2012/03/30 17:23:09 Do you need this for anything? Unless you have a n
+ DCHECK(other);
+ PROCESS_INFORMATION temp = other->process_information_;
+ other->process_information_ = process_information_;
+ process_information_ = temp;
+}
+
+bool ScopedProcessInformation::DuplicateFrom(
brettw 2012/03/30 17:23:09 I'm also wondering about the use case for this fun
+ const ScopedProcessInformation& other) {
+ DCHECK(!IsValid()) << "target ScopedProcessInformation must be NULL";
+ DCHECK(other.IsValid()) << "source ScopedProcessInformation must be valid";
+
+ ScopedHandle duplicate_process;
+ ScopedHandle duplicate_thread;
+
+ if (CheckAndDuplicateHandle(other.process_handle(),
+ duplicate_process.Receive()) &&
+ CheckAndDuplicateHandle(other.thread_handle(),
+ duplicate_thread.Receive())) {
+ process_information_.dwProcessId = other.process_id();
+ process_information_.dwThreadId = other.thread_id();
+ process_information_.hProcess = duplicate_process.Take();
+ process_information_.hThread = duplicate_thread.Take();
+ return true;
+ }
+
+ return false;
+}
+
+PROCESS_INFORMATION ScopedProcessInformation::Take() {
+ PROCESS_INFORMATION process_information = process_information_;
+ Reset();
+ return process_information;
+}
+
+HANDLE ScopedProcessInformation::TakeProcessHandle() {
+ HANDLE process = process_information_.hProcess;
+ process_information_.hProcess = NULL;
+ process_information_.dwProcessId = 0;
+ return process;
+}
+
+HANDLE ScopedProcessInformation::TakeThreadHandle() {
+ HANDLE thread = process_information_.hThread;
+ process_information_.hThread = NULL;
+ process_information_.dwThreadId = 0;
+ return thread;
+}
+
+void ScopedProcessInformation::Reset() {
+ process_information_.hThread = NULL;
+ process_information_.hProcess = NULL;
+ process_information_.dwProcessId = 0;
+ process_information_.dwThreadId = 0;
+}
+
+} // namespace win
+} // namespace base
« no previous file with comments | « base/win/scoped_process_information.h ('k') | base/win/scoped_process_information_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698