diff options
-rw-r--r-- | base/base.gypi | 1 | ||||
-rw-r--r-- | base/win/scoped_handle.cc | 88 | ||||
-rw-r--r-- | base/win/scoped_handle.h | 39 | ||||
-rw-r--r-- | chrome/service/cloud_print/print_system_win.cc | 3 | ||||
-rw-r--r-- | cloud_print/service/win/cloud_print_service.cc | 3 | ||||
-rw-r--r-- | printing/backend/win_helper.h | 3 | ||||
-rw-r--r-- | remoting/base/scoped_sc_handle_win.h | 3 |
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 |