From 58d65b17ea30efdeca910bfd5e2c979c040df8e6 Mon Sep 17 00:00:00 2001 From: "Vicente J. Botet Escriba" Date: Sun, 4 Dec 2011 23:06:24 +0000 Subject: [PATCH] Thread: #5859 win32 shared_mutex constructor leaks on exceptions [SVN r75806] --- include/boost/thread/win32/shared_mutex.hpp | 55 +++++++++++-------- .../boost/thread/win32/thread_primitives.hpp | 43 +++++++++------ 2 files changed, 59 insertions(+), 39 deletions(-) diff --git a/include/boost/thread/win32/shared_mutex.hpp b/include/boost/thread/win32/shared_mutex.hpp index 58fc6224..06675139 100644 --- a/include/boost/thread/win32/shared_mutex.hpp +++ b/include/boost/thread/win32/shared_mutex.hpp @@ -23,7 +23,7 @@ namespace boost { private: shared_mutex(shared_mutex const&); - shared_mutex& operator=(shared_mutex const&); + shared_mutex& operator=(shared_mutex const&); private: struct state_data { @@ -39,7 +39,7 @@ namespace boost return *reinterpret_cast(&lhs)==*reinterpret_cast(&rhs); } }; - + template T interlocked_compare_exchange(T* target,T new_value,T comparand) @@ -67,20 +67,31 @@ namespace boost { BOOST_VERIFY(detail::win32::ReleaseSemaphore(semaphores[exclusive_sem],1,0)!=0); } - + if(old_state.shared_waiting || old_state.exclusive_waiting) { BOOST_VERIFY(detail::win32::ReleaseSemaphore(semaphores[unlock_sem],old_state.shared_waiting + (old_state.exclusive_waiting?1:0),0)!=0); } } - + public: shared_mutex() { semaphores[unlock_sem]=detail::win32::create_anonymous_semaphore(0,LONG_MAX); - semaphores[exclusive_sem]=detail::win32::create_anonymous_semaphore(0,LONG_MAX); - upgrade_sem=detail::win32::create_anonymous_semaphore(0,LONG_MAX); + semaphores[exclusive_sem]=detail::win32::create_anonymous_semaphore_nothrow(0,LONG_MAX); + if (!semaphores[exclusive_sem]) + { + detail::win32::release_semaphore(semaphores[unlock_sem],LONG_MAX); + boost::throw_exception(thread_resource_error()); + } + upgrade_sem=detail::win32::create_anonymous_semaphore_nothrow(0,LONG_MAX); + if (!upgrade_sem) + { + detail::win32::release_semaphore(semaphores[unlock_sem],LONG_MAX); + detail::win32::release_semaphore(semaphores[exclusive_sem],LONG_MAX); + boost::throw_exception(thread_resource_error()); + } state_data state_={0}; state=state_; } @@ -106,7 +117,7 @@ namespace boost return false; } } - + state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state); if(current_state==old_state) { @@ -165,7 +176,7 @@ namespace boost { return true; } - + unsigned long const res=detail::win32::WaitForSingleObject(semaphores[unlock_sem],::boost::detail::get_milliseconds_until(wait_until)); if(res==detail::win32::timeout) { @@ -202,7 +213,7 @@ namespace boost } return false; } - + BOOST_ASSERT(res==0); } } @@ -214,7 +225,7 @@ namespace boost { state_data new_state=old_state; bool const last_reader=!--new_state.shared_count; - + if(last_reader) { if(new_state.upgrade) @@ -232,7 +243,7 @@ namespace boost new_state.shared_waiting=0; } } - + state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state); if(current_state==old_state) { @@ -278,7 +289,7 @@ namespace boost { new_state.exclusive=true; } - + state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state); if(current_state==old_state) { @@ -306,7 +317,7 @@ namespace boost { boost::throw_exception(boost::lock_error()); } - + new_state.exclusive_waiting_blocked=true; } else @@ -426,7 +437,7 @@ namespace boost { return; } - + BOOST_VERIFY(!detail::win32::WaitForSingleObject(semaphores[unlock_sem],detail::win32::infinite)); } } @@ -450,7 +461,7 @@ namespace boost } new_state.upgrade=true; } - + state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state); if(current_state==old_state) { @@ -469,7 +480,7 @@ namespace boost state_data new_state=old_state; new_state.upgrade=false; bool const last_reader=!--new_state.shared_count; - + if(last_reader) { if(new_state.exclusive_waiting) @@ -479,7 +490,7 @@ namespace boost } new_state.shared_waiting=0; } - + state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state); if(current_state==old_state) { @@ -500,13 +511,13 @@ namespace boost { state_data new_state=old_state; bool const last_reader=!--new_state.shared_count; - + if(last_reader) { new_state.upgrade=false; new_state.exclusive=true; } - + state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state); if(current_state==old_state) { @@ -545,7 +556,7 @@ namespace boost } release_waiters(old_state); } - + void unlock_and_lock_shared() { state_data old_state=state; @@ -570,7 +581,7 @@ namespace boost } release_waiters(old_state); } - + void unlock_upgrade_and_lock_shared() { state_data old_state=state; @@ -594,7 +605,7 @@ namespace boost } release_waiters(old_state); } - + }; } diff --git a/include/boost/thread/win32/thread_primitives.hpp b/include/boost/thread/win32/thread_primitives.hpp index 9b20e860..0166f37d 100644 --- a/include/boost/thread/win32/thread_primitives.hpp +++ b/include/boost/thread/win32/thread_primitives.hpp @@ -3,8 +3,8 @@ // win32_thread_primitives.hpp // -// (C) Copyright 2005-7 Anthony Williams -// (C) Copyright 2007 David Deakins +// (C) Copyright 2005-7 Anthony Williams +// (C) Copyright 2007 David Deakins // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at @@ -94,7 +94,7 @@ namespace boost { namespace win32 { - + # ifdef _WIN64 typedef unsigned __int64 ulong_ptr; # else @@ -170,20 +170,20 @@ namespace boost auto_reset_event=false, manual_reset_event=true }; - + enum initial_event_state { event_initially_reset=false, event_initially_set=true }; - + inline handle create_anonymous_event(event_type type,initial_event_state state) { -#if !defined(BOOST_NO_ANSI_APIS) +#if !defined(BOOST_NO_ANSI_APIS) handle const res=win32::CreateEventA(0,type,state,0); #else handle const res=win32::CreateEventW(0,type,state,0); -#endif +#endif if(!res) { boost::throw_exception(thread_resource_error()); @@ -193,17 +193,26 @@ namespace boost inline handle create_anonymous_semaphore(long initial_count,long max_count) { -#if !defined(BOOST_NO_ANSI_APIS) +#if !defined(BOOST_NO_ANSI_APIS) handle const res=CreateSemaphoreA(0,initial_count,max_count,0); #else handle const res=CreateSemaphoreW(0,initial_count,max_count,0); -#endif +#endif if(!res) { boost::throw_exception(thread_resource_error()); } return res; } + inline handle create_anonymous_semaphore_nothrow(long initial_count,long max_count) + { +#if !defined(BOOST_NO_ANSI_APIS) + handle const res=CreateSemaphoreA(0,initial_count,max_count,0); +#else + handle const res=CreateSemaphoreW(0,initial_count,max_count,0); +#endif + return res; + } inline handle duplicate_handle(handle source) { @@ -237,7 +246,7 @@ namespace boost BOOST_VERIFY(CloseHandle(handle_to_manage)); } } - + public: explicit handle_manager(handle handle_to_manage_): handle_to_manage(handle_to_manage_) @@ -245,7 +254,7 @@ namespace boost handle_manager(): handle_to_manage(0) {} - + handle_manager& operator=(handle new_handle) { cleanup(); @@ -279,13 +288,13 @@ namespace boost { return !handle_to_manage; } - + ~handle_manager() { cleanup(); } }; - + } } } @@ -318,7 +327,7 @@ namespace boost { return _interlockedbittestandreset(x,bit)!=0; } - + } } } @@ -337,7 +346,7 @@ namespace boost mov edx,x; lock bts [edx],eax; setc al; - }; + }; } inline bool interlocked_bit_test_and_reset(long* x,long bit) @@ -347,9 +356,9 @@ namespace boost mov edx,x; lock btr [edx],eax; setc al; - }; + }; } - + } } }