summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--base/base.gypi1
-rw-r--r--base/win/scoped_handle.cc88
-rw-r--r--base/win/scoped_handle.h39
-rw-r--r--chrome/service/cloud_print/print_system_win.cc3
-rw-r--r--cloud_print/service/win/cloud_print_service.cc3
-rw-r--r--printing/backend/win_helper.h3
-rw-r--r--remoting/base/scoped_sc_handle_win.h3
7 files changed, 134 insertions, 6 deletions
diff --git a/base/base.gypi b/base/base.gypi
index b17f391..101cdf9 100644
--- a/base/base.gypi
+++ b/base/base.gypi
@@ -446,6 +446,7 @@
'win/scoped_com_initializer.h',
'win/scoped_comptr.h',
'win/scoped_gdi_object.h',
+ 'win/scoped_handle.cc',
'win/scoped_handle.h',
'win/scoped_hdc.h',
'win/scoped_hglobal.h',
diff --git a/base/win/scoped_handle.cc b/base/win/scoped_handle.cc
new file mode 100644
index 0000000..9ec551b
--- /dev/null
+++ b/base/win/scoped_handle.cc
@@ -0,0 +1,88 @@
+// 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_handle.h"
+
+#include <map>
+#include <set>
+
+#include "base/debug/alias.h"
+#include "base/lazy_instance.h"
+#include "base/synchronization/lock.h"
+#include "base/win/windows_version.h"
+
+namespace {
+
+struct Info {
+ const void* owner;
+ const void* pc;
+ DWORD thread_id;
+};
+typedef std::map<HANDLE, Info> HandleMap;
+
+base::LazyInstance<HandleMap>::Leaky g_handle_map = LAZY_INSTANCE_INITIALIZER;
+base::LazyInstance<std::set<const void*> >::Leaky g_owner_set =
+ LAZY_INSTANCE_INITIALIZER;
+base::LazyInstance<base::Lock>::Leaky g_lock = LAZY_INSTANCE_INITIALIZER;
+
+} // namespace
+
+namespace base {
+namespace win {
+
+// Static.
+void VerifierTraits::StartTracking(HANDLE handle, const void* owner,
+ const void* pc) {
+ if (OSInfo::GetInstance()->version() > VERSION_XP)
+ return;
+
+ // Grab the thread id before the lock.
+ DWORD thread_id = GetCurrentThreadId();
+
+ AutoLock(g_lock.Get());
+
+ if (handle == INVALID_HANDLE_VALUE) {
+ // Cannot track this handle.
+ g_owner_set.Get().insert(owner);
+ return;
+ }
+
+ Info handle_info = { owner, pc, thread_id };
+ std::pair<HANDLE, Info> item(handle, handle_info);
+ std::pair<HandleMap::iterator, bool> result = g_handle_map.Get().insert(item);
+ if (!result.second) {
+ Info other = result.first->second;
+ debug::Alias(&other);
+ CHECK(false);
+ }
+}
+
+// Static.
+void VerifierTraits::StopTracking(HANDLE handle, const void* owner,
+ const void* pc) {
+ if (OSInfo::GetInstance()->version() > VERSION_XP)
+ return;
+
+ AutoLock(g_lock.Get());
+ HandleMap::iterator i = g_handle_map.Get().find(handle);
+ if (i == g_handle_map.Get().end()) {
+ std::set<const void*>::iterator j = g_owner_set.Get().find(owner);
+ if (j != g_owner_set.Get().end()) {
+ g_owner_set.Get().erase(j);
+ return;
+ }
+ CHECK(false);
+ }
+
+ Info other = i->second;
+ if (other.owner != owner) {
+ debug::Alias(&other);
+ CHECK(false);
+ }
+
+ g_handle_map.Get().erase(i);
+}
+
+} // namespace win
+} // namespace base
diff --git a/base/win/scoped_handle.h b/base/win/scoped_handle.h
index a18f65a..287ac6e 100644
--- a/base/win/scoped_handle.h
+++ b/base/win/scoped_handle.h
@@ -8,7 +8,9 @@
#include <windows.h>
+#include "base/base_export.h"
#include "base/basictypes.h"
+#include "base/location.h"
#include "base/logging.h"
namespace base {
@@ -21,7 +23,7 @@ namespace win {
// and INVALID_HANDLE_VALUE (-1) for Win32 handles.
// - Receive() method allows to receive a handle value from a function that
// takes a raw handle pointer only.
-template <class Traits>
+template <class Traits, class Verifier>
class GenericScopedHandle {
public:
typedef typename Traits::Handle Handle;
@@ -46,6 +48,8 @@ class GenericScopedHandle {
if (Traits::IsHandleValid(handle)) {
handle_ = handle;
+ Verifier::StartTracking(handle, this,
+ tracked_objects::GetProgramCounter());
}
}
}
@@ -60,6 +64,10 @@ class GenericScopedHandle {
Handle* Receive() {
DCHECK(!Traits::IsHandleValid(handle_)) << "Handle must be NULL";
+
+ // We cannot track this case :(. Just tell the verifier about it.
+ Verifier::StartTracking(INVALID_HANDLE_VALUE, this,
+ tracked_objects::GetProgramCounter());
return &handle_;
}
@@ -67,6 +75,7 @@ class GenericScopedHandle {
Handle Take() {
Handle temp = handle_;
handle_ = Traits::NullHandle();
+ Verifier::StopTracking(temp, this, tracked_objects::GetProgramCounter());
return temp;
}
@@ -76,6 +85,8 @@ class GenericScopedHandle {
if (!Traits::CloseHandle(handle_)) {
CHECK(false);
}
+ Verifier::StopTracking(handle_, this,
+ tracked_objects::GetProgramCounter());
handle_ = Traits::NullHandle();
}
}
@@ -110,7 +121,31 @@ class HandleTraits {
DISALLOW_IMPLICIT_CONSTRUCTORS(HandleTraits);
};
-typedef GenericScopedHandle<HandleTraits> ScopedHandle;
+// Do-nothing verifier.
+class DummyVerifierTraits {
+ public:
+ typedef HANDLE Handle;
+
+ static void StartTracking(HANDLE handle, const void* owner, const void* pc) {}
+ static void StopTracking(HANDLE handle, const void* owner, const void* pc) {}
+
+ private:
+ DISALLOW_IMPLICIT_CONSTRUCTORS(DummyVerifierTraits);
+};
+
+// Performs actual run-time tracking.
+class BASE_EXPORT VerifierTraits {
+ public:
+ typedef HANDLE Handle;
+
+ static void StartTracking(HANDLE handle, const void* owner, const void* pc);
+ static void StopTracking(HANDLE handle, const void* owner, const void* pc);
+
+ private:
+ DISALLOW_IMPLICIT_CONSTRUCTORS(VerifierTraits);
+};
+
+typedef GenericScopedHandle<HandleTraits, DummyVerifierTraits> ScopedHandle;
} // namespace win
} // namespace base
diff --git a/chrome/service/cloud_print/print_system_win.cc b/chrome/service/cloud_print/print_system_win.cc
index 1509c77..3d787e0 100644
--- a/chrome/service/cloud_print/print_system_win.cc
+++ b/chrome/service/cloud_print/print_system_win.cc
@@ -55,7 +55,8 @@ class PrinterChangeHandleTraits {
DISALLOW_IMPLICIT_CONSTRUCTORS(PrinterChangeHandleTraits);
};
-typedef base::win::GenericScopedHandle<PrinterChangeHandleTraits>
+typedef base::win::GenericScopedHandle<PrinterChangeHandleTraits,
+ base::win::DummyVerifierTraits>
ScopedPrinterChangeHandle;
class DevMode {
diff --git a/cloud_print/service/win/cloud_print_service.cc b/cloud_print/service/win/cloud_print_service.cc
index 366ea2d..d53d7a7 100644
--- a/cloud_print/service/win/cloud_print_service.cc
+++ b/cloud_print/service/win/cloud_print_service.cc
@@ -53,7 +53,8 @@ class ServiceHandleTraits {
DISALLOW_IMPLICIT_CONSTRUCTORS(ServiceHandleTraits);
};
-typedef base::win::GenericScopedHandle<ServiceHandleTraits> ServiceHandle;
+typedef base::win::GenericScopedHandle<
+ ServiceHandleTraits, base::win::DummyVerifierTraits> ServiceHandle;
HRESULT HResultFromLastError() {
HRESULT hr = HRESULT_FROM_WIN32(GetLastError());
diff --git a/printing/backend/win_helper.h b/printing/backend/win_helper.h
index 87cae3c..abfe66c 100644
--- a/printing/backend/win_helper.h
+++ b/printing/backend/win_helper.h
@@ -42,7 +42,8 @@ class PrinterHandleTraits {
DISALLOW_IMPLICIT_CONSTRUCTORS(PrinterHandleTraits);
};
-typedef base::win::GenericScopedHandle<PrinterHandleTraits> ScopedPrinterHandle;
+typedef base::win::GenericScopedHandle<
+ PrinterHandleTraits, base::win::DummyVerifierTraits> ScopedPrinterHandle;
// Wrapper class to wrap the XPS APIs (PTxxx APIs). This is needed because these
diff --git a/remoting/base/scoped_sc_handle_win.h b/remoting/base/scoped_sc_handle_win.h
index 508f5f5..69cd569 100644
--- a/remoting/base/scoped_sc_handle_win.h
+++ b/remoting/base/scoped_sc_handle_win.h
@@ -34,7 +34,8 @@ class ScHandleTraits {
DISALLOW_IMPLICIT_CONSTRUCTORS(ScHandleTraits);
};
-typedef base::win::GenericScopedHandle<ScHandleTraits> ScopedScHandle;
+typedef base::win::GenericScopedHandle<
+ ScHandleTraits, base::win::DummyVerifierTraits> ScopedScHandle;
} // namespace remoting