Boost logo

Threads-Devel :

From: Johan Nilsson (r.johan.nilsson_at_[hidden])
Date: 2007-04-12 02:26:15


Hi,

this is mostly a repost from the boost user list, hoping to get some fresh
ideas. I've been grokking the tss code and can't find any problems there,
even though it is admittedly hard to verify by inspection only.

Original posting follows below. I've updated to the very latest RC_1_34_0
from CVS since.

/ Johan

--------------------------------------
Hi,

I've been trying to resolve a problem which seems to be related to TSS and
the static build of the Boost.Thread library.

I'm using MSVC 8.0 (no SP applied) under WinXP and Boost RC_1_34_0 (CVS)
from last week.

The problem only manifests itself on one machine and only for release
builds. The machine in question is a XP SP2 Pro machine with dual
processors. The same code works fine under a XP SP2 Pro SMP with 2 CPUs + HT
enabled, and also under OpenSUSE 10.0 + gcc 4.0 (same hardware as the
failing machine).

What seems to be happening is that the thread_specific_ptr's cleanup method
is called twice with a non-null pointer for the main thread of the
application. Changing the application to use the DLL variant of the thread
library cures the problem (or, at least the application no longer crashes
with an access violation).

The good news is that the problem is consistent - it always occurs for my
test application. The bad news is that the environment is pretty complex,
and I can't reproduce the problem with a simple test case. I figured I could
attach some output from my test application together with source code
excerpts (with tracing hacks added) and hope that somebody could give me a
hint on what's actually going on. I added debug symbols and disabled
optimization for the release build to try and get better call stack
information, but the call stack still seems a bit messed up.

Sorry for the longish output, but here goes:

-------------------------
excerpt from Context.cpp
-------------------------

#ifdef BOOST_MSVC
__declspec(thread) static int all = 0, reals = 0;
#endif

/*

MapT = std::map<
            "typeinfo wrapper",
            std::stack<
                boost::any
>
>

MapPtrT = boost::thread_specific_ptr<MapT>

*/

//
// STATIC DATA
//
Context::MapPtrT Context::g_pCtxMap(&Context::Cleanup);

void
Context::Cleanup(MapT* pCtxMap)
{
#ifdef BOOST_MSVC
 all++;

 DWORD thread = ::GetCurrentThreadId();

 std::cout << std::hex << std::setw(8) << thread << ": Context::Cleanup(" <<
pCtxMap
      << "), all: " << all
      << ", reals: " << reals
      << std::endl;

 if (pCtxMap)
 {
  reals++;

  std::cout << "Clearing, reals: " << reals << std::endl;
  assert(reals == 1);
  pCtxMap->clear();

  std::cout << "Deleting" << std::endl;
  delete pCtxMap;
 }
#else
 delete pCtxMap;
#endif
}

//
// HELPERS
//
Context::MapT&
Context::ContextMap()
{
 if (!g_pCtxMap.get())
 {
  g_pCtxMap.reset(new MapT);
 }

 return *(g_pCtxMap.get());
}

--------------------
RELEASE BUILD OUTPUT
--------------------

testing.unit-test
C:\users\cc\builds\checkout\knmc\build\src\libs\oasis\oasistest\msvc-8.0\release\debug-symbols-on\optimization-off
\threading-multi\oasistest.passed
Running 402 test cases...
     2b4: Context::Cleanup(00D22528), all: 1, reals: 0
Clearing, reals: 1
Deleting
     7d8: Context::Cleanup(00000000), all: 1, reals: 0
     754: Context::Cleanup(00000000), all: 1, reals: 0
      bc: Context::Cleanup(00000000), all: 1, reals: 0
     1b4: Context::Cleanup(00000000), all: 1, reals: 0
      9c: Context::Cleanup(00000000), all: 1, reals: 0
     5b8: Context::Cleanup(00000000), all: 1, reals: 0
     530: Context::Cleanup(00000000), all: 1, reals: 0
     39c: Context::Cleanup(00000000), all: 1, reals: 0
     58c: Context::Cleanup(00000000), all: 1, reals: 0
     6b8: Context::Cleanup(00000000), all: 1, reals: 0
     318: Context::Cleanup(00000000), all: 1, reals: 0

*** No errors detected
     134: Context::Cleanup(00D253F8), all: 1, reals: 0
Clearing, reals: 1
Deleting
     134: Context::Cleanup(00D24658), all: 2, reals: 1
Clearing, reals: 2

----------------
Error popup occurs here:
----------------

Unhandled exception at 0x0054ea2a in oasistest.exe: 0xC0000005: Access
violation reading location 0x00000025.

------------------
Call stack when entering the debugger:
------------------

  oasistest.exe!std::_Tree<std::_Tmap_traits<oasis::utility::detail::ContextKey,std::stack<boost::any,std::deque<boost::any,std::allocator<boost::any>
>
>,std::less<oasis::utility::detail::ContextKey>,std::allocator<std::pair<oasis::utility::detail::ContextKeyconst,std::stack<boost::any,std::deque<boost::any,std::allocator<boost::any> > > > >,0> >::_Erase(std::_Tree_nod<std::_Tmap_traits<oasis::utility::detail::ContextKey,std::stack<boost::any,std::deque<boost::any,std::allocator<boost::any> > >,std::less<oasis::utility::detail::ContextKey>,std::allocator<std::pair<oasis::utility::detail::ContextKeyconst,std::stack<boost::any,std::deque<boost::any,std::allocator<boost::any> > > > >,0> >::_Node * _Rootnode=0x00000000) Line 1073 + 0x11 bytes C++>oasistest.exe!std::_Tree<std::_Tmap_traits<oasis::utility::detail::ContextKey,std::stack<boost::any,std::deque<boost::any,std::allocator<boost::any>> >>>,std::less<oasis::utility::detail::ContextKey>,std::allocator<std::pair<oasis::utility::detail::ContextKey> const> ,std::stack<boost::any,std::deque<boost::any,std::allocator<boost::any> >> > > >,0>>>::_Erase(std::_Tree_nod<std::_Tmap_traits<oasis::utility::detail:
:ContextKey,std::stack<boost::any,std::deque<boost::any,std::allocator<boost::any>> >>>,std::less<oasis::utility::detail::ContextKey>,std::allocator<std::pair<oasis::utility::detail::ContextKey> const> ,std::stack<boost::any,std::deque<boost::any,std::allocator<boost::any> >> > > >,0> >::_Node * _Rootnode=0x00d24df0) Line 1076 C++ oasistest.exe!std::_Tree<std::_Tmap_traits<oasis::utility::detail::ContextKey,std::stack<boost::any,std::deque<boost::any,std::allocator<boost::any> > >,std::less<oasis::utility::detail::ContextKey>,std::allocator<std::pair<oasis::utility::detail::ContextKeyconst,std::stack<boost::any,std::deque<boost::any,std::allocator<boost::any> > > > >,0> >::clear() Line 955 C++ oasistest.exe!oasis::utility::Context::Cleanup(std::map<oasis::utility::detail::ContextKey,std::stack<boost::any,std::deque<boost::any,std::allocator<boost::any> > >,std::less<oasis::utility::detail::ContextKey>,std::allocator<std::pair<oasis::utility::detail::ContextKeyconst,std::stack<boost::any,std::deque<boos
t::any,std::allocator<boost::any> > > > > > * pCtxMap=[0]()) Line 48 C++ oasistest.exe!boost::detail::function::void_function_invoker1<void(__cdecl*)(boost::shared_ptr<RCF::Session>*),void,boost::shared_ptr<RCF::Session>*>::invoke(boost::detail::function::function_buffer & function_ptr={...},boost::shared_ptr<RCF::Session> * a0=0x00d24658) Line 114 + 0x7 bytes C++ oasistest.exe!boost::function1<void,boost::shared_ptr<RCF::Session>*,std::allocator<boost::function_base> >::operator()(boost::shared_ptr<RCF::Session> * a0=0x00d24658) Line 692 +0x15 bytes C++ oasistest.exe!boost::detail::function::void_function_obj_invoker1<boost::detail::tss_adapter<boost::shared_ptr<rsdb::detail::IRsdbApi> >,void,void *>::invoke(boost::detail::function::function_buffer &function_obj_ptr={...}, void * a0=0x00d24658) Line 156 C++ oasistest.exe!boost::function1<void,void*,std::allocator<boost::function_base> >::operator()() + 0x4e bytes C++ oasistest.exe!boost::detail::tss::cleanup() + 0x78 bytes C++ oasistest.exe!boos
t::thread_specific_ptr<boost::shared_ptr<RCF::Session> >::~thread_specific_ptr<boost::shared_ptr<RCF::Session> >() Line 90 + 0x5ebytes C++ oasistest.exe!`dynamic atexit destructor for'oasis::utility::Context::g_pCtxMap''() + 0xe bytes C++ msvcr80.dll!doexit(int code=0, int quick=0, int retcaller=0) Line 553 C msvcr80.dll!exit(int code=0) Line 398 + 0xd bytes C oasistest.exe!__tmainCRTStartup() Line 603 C kernel32.dll!7c816fd7() [Frames below may be incorrect and/or missing, no symbols loaded forkernel32.dll] kernel32.dll!7c816fd7()------------------DEBUG BUILD OUTPUT------------------testing.unit-test C:\users\cc\builds\checkout\knmc\build\src\libs\oaRunning 402 test cases... 608: Context::Cleanup(0100E720), all: 1, reals: 0Clearing, reals: 1Deleting 1a8: Context::Cleanup(00000000), all: 1, reals: 0 600: Context::Cleanup(00000000), all: 1, reals: 0 128: Context::Cleanup(00000000), all: 1, reals: 0 31c: Context::Cleanup(00000000), all: 1, reals: 0 e4: Context::Cleanup(0000
0000), all: 1, reals: 0 7d0: Context::Cleanup(00000000), all: 1, reals: 0 168: Context::Cleanup(00000000), all: 1, reals: 0 f8: Context::Cleanup(00000000), all: 1, reals: 0 52c: Context::Cleanup(00000000), all: 1, reals: 0 1a0: Context::Cleanup(00000000), all: 1, reals: 0 784: Context::Cleanup(00000000), all: 1, reals: 0*** No errors detected 6bc: Context::Cleanup(00FE3838), all: 1, reals: 0Clearing, reals: 1Deleting...updated 5 targets...-----------------------------------/ Johan


Threads-Devel list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk