Boost logo

Boost Users :

From: Johan Nilsson (r.johan.nilsson_at_[hidden])
Date: 2007-04-10 09:01:42


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

//
// 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::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=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::ContextKey
const
,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::ContextKey
const
,std::stack<boost::any,std::deque<boost::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!boost::thread_specific_ptr<boost::shared_ptr<RCF::Session>
>::~thread_specific_ptr<boost::shared_ptr<RCF::Session> >() Line 90 + 0x5e
bytes 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 for
kernel32.dll]
  kernel32.dll!7c816fd7()

------------------
DEBUG BUILD OUTPUT
------------------
testing.unit-test C:\users\cc\builds\checkout\knmc\build\src\libs\oa
Running 402 test cases...
     608: Context::Cleanup(0100E720), all: 1, reals: 0
Clearing, reals: 1
Deleting
     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(00000000), 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: 0
Clearing, reals: 1
Deleting
...updated 5 targets...

-----------------------------------

/ Johan


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net