[Boost-bugs] [Boost C++ Libraries] #8544: Calling managed DLL from within boost::context may cause a crash

Subject: [Boost-bugs] [Boost C++ Libraries] #8544: Calling managed DLL from within boost::context may cause a crash
From: Boost C++ Libraries (noreply_at_[hidden])
Date: 2013-05-03 00:50:53


#8544: Calling managed DLL from within boost::context may cause a crash
-------------------------------------+--------------------------------------
 Reporter: vitaly.blinov@… | Owner: olli
     Type: Bugs | Status: new
Milestone: To Be Determined | Component: context
  Version: Boost 1.53.0 | Severity: Problem
 Keywords: context, coroutine |
-------------------------------------+--------------------------------------
 Only Windows platform is affected.

 If the code running in the context (coroutine) invokes anything that
 involves crossing clr.dll (mscorwks.dll) boundary, a crash occurs with
 about 50% probability.

 My investigation showed that call stack of the problem is consistent with
 clr.dll!Thread::InitThread throwing OutOfMemory exception. With some deep
 debugging I narrowed the problem down to CommitThreadStack function inside
 the clr.dll. That method accesses a dword located at FS:[0xE0C] (this is
 called "deallocaton stack" on
 [http://en.wikipedia.org/wiki/Win32_Thread_Information_Block TIB wiki
 page]) and compares it with current top of the stack (FS:[0x4]). It
 appears that exception is thrown if FS:[0xE0C] value is greater than
 FS:[0x4] (or, perhaps, FS:[0x8]).
 That variable is not very well documented, but I believe the pair
 FS:[0xE0C] - FS:[0x4] defines the maximum stack size. On windows 7, the
 difference between these is always 0x100000, which gives stack size of 1M.
 Interestingly, that always the case even if the fiber or thread were
 created with smaller stack size.

 jump_context never touches that variable. As a result, the value in
 FS:[0xE0C] is defined by the calling thread, and therefore it contains
 arbitrary value. If it is greater than current top of stack, problem
 occurs.

 clr.dll!CommitThreadStack also appears to be accessing FS:[0xF78], but
 it's purpose and whether the value stored in it affects the behavior is
 unknown.

 My current workaround of writing current bottom of the stack to FS:[0xE0C]
 prior to calling managed DLL appears to be working:

 (MS VS specific)
 {{{#!cpp
 DWORD store = __readfsdword(0xE0C);
 __writefsdword(0xE0C, __readfsdword(0x8));
 call_managed_dll();
 __writefsdword(0xE0C, store);
 }}}


 This bug is very obscure and so far I only managed to observe it on
 Windows7 and Windows server 2008.

 Suggested fix: Store and restore FS:[0xE0C] in jump_context.

-- 
Ticket URL: <https://svn.boost.org/trac/boost/ticket/8544>
Boost C++ Libraries <http://www.boost.org/>
Boost provides free peer-reviewed portable C++ source libraries.

This archive was generated by hypermail 2.1.7 : 2017-02-16 18:50:13 UTC