Boost C++ Libraries: Ticket #7152: Interprocess 1.50 windows_bootstamp fails when COM already initialized in multithreaded https://svn.boost.org/trac10/ticket/7152 <p> The windows_bootstamp class fails to obtain a bootstamp if the current thread has already been COM-initialized in MULTITHREADED mode. This is due to (detail/win32api.hpp) calling <a class="missing wiki">CoInitialize</a>(0) and failing to test for RPC_E_CHANGED_MODE. </p> <p> This causes opening of a shared_memory_object to fail due to a file path mismatch if one process' thread was not running in a multithreaded COM thread. If both processing were running multithreaded, the problem is masked -- the bootstamp returns an empty string and thus the shared memory file path is the same in both cases. </p> <p> A slight modification to the example program in the shared memory documentation (<a href="http://www.boost.org/doc/libs/1_50_0/doc/html/interprocess/sharedmemorybetweenprocesses.html#interprocess.sharedmemorybetweenprocesses.sharedmemory">http://www.boost.org/doc/libs/1_50_0/doc/html/interprocess/sharedmemorybetweenprocesses.html#interprocess.sharedmemorybetweenprocesses.sharedmemory</a>) displays the problem: </p> <div class="wikipage" style="font-size: 80%"><div class="wiki-code"><div class="code"><pre> <span class="cp">#include</span> <span class="cpf">&lt;boost/interprocess/shared_memory_object.hpp&gt;</span><span class="cp"></span> <span class="cp">#include</span> <span class="cpf">&lt;boost/interprocess/mapped_region.hpp&gt;</span><span class="cp"></span> <span class="cp">#include</span> <span class="cpf">&lt;cstring&gt;</span><span class="cp"></span> <span class="cp">#include</span> <span class="cpf">&lt;cstdlib&gt;</span><span class="cp"></span> <span class="cp">#include</span> <span class="cpf">&lt;string&gt;</span><span class="cp"></span> <span class="cp">#include</span> <span class="cpf">&lt;atlbase.h&gt;</span><span class="cp"></span> <span class="k">struct</span> <span class="n">co_uninitializer</span><span class="p">{</span> <span class="o">~</span><span class="n">co_uninitializer</span><span class="p">()</span> <span class="p">{</span> <span class="n">CoUninitialize</span><span class="p">();</span> <span class="p">}</span> <span class="p">};</span> <span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> <span class="p">{</span> <span class="k">using</span> <span class="k">namespace</span> <span class="n">boost</span><span class="o">::</span><span class="n">interprocess</span><span class="p">;</span> <span class="k">if</span><span class="p">(</span><span class="n">argc</span> <span class="o">==</span> <span class="mi">1</span><span class="p">){</span> <span class="c1">//Parent process</span> <span class="c1">//Remove shared memory on construction and destruction</span> <span class="k">struct</span> <span class="n">shm_remove</span> <span class="p">{</span> <span class="n">shm_remove</span><span class="p">()</span> <span class="p">{</span> <span class="n">shared_memory_object</span><span class="o">::</span><span class="n">remove</span><span class="p">(</span><span class="s">&quot;MySharedMemory&quot;</span><span class="p">);</span> <span class="p">}</span> <span class="o">~</span><span class="n">shm_remove</span><span class="p">(){</span> <span class="n">shared_memory_object</span><span class="o">::</span><span class="n">remove</span><span class="p">(</span><span class="s">&quot;MySharedMemory&quot;</span><span class="p">);</span> <span class="p">}</span> <span class="p">}</span> <span class="n">remover</span><span class="p">;</span> <span class="c1">//Create a shared memory object.</span> <span class="n">shared_memory_object</span> <span class="n">shm</span> <span class="p">(</span><span class="n">create_only</span><span class="p">,</span> <span class="s">&quot;MySharedMemory&quot;</span><span class="p">,</span> <span class="n">read_write</span><span class="p">);</span> <span class="c1">//Set size</span> <span class="n">shm</span><span class="p">.</span><span class="n">truncate</span><span class="p">(</span><span class="mi">1000</span><span class="p">);</span> <span class="c1">//Map the whole shared memory in this process</span> <span class="n">mapped_region</span> <span class="n">region</span><span class="p">(</span><span class="n">shm</span><span class="p">,</span> <span class="n">read_write</span><span class="p">);</span> <span class="c1">//Write all the memory to 1</span> <span class="n">std</span><span class="o">::</span><span class="n">memset</span><span class="p">(</span><span class="n">region</span><span class="p">.</span><span class="n">get_address</span><span class="p">(),</span> <span class="mi">1</span><span class="p">,</span> <span class="n">region</span><span class="p">.</span><span class="n">get_size</span><span class="p">());</span> <span class="c1">//Launch child process</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">s</span><span class="p">(</span><span class="n">argv</span><span class="p">[</span><span class="mi">0</span><span class="p">]);</span> <span class="n">s</span> <span class="o">=</span> <span class="s">&quot;</span><span class="se">\&quot;</span><span class="s">&quot;</span> <span class="o">+</span> <span class="n">s</span> <span class="o">+</span> <span class="s">&quot;</span><span class="se">\&quot;</span><span class="s">&quot;</span> <span class="o">+</span> <span class="s">&quot; child &quot;</span><span class="p">;</span> <span class="k">if</span><span class="p">(</span><span class="mi">0</span> <span class="o">!=</span> <span class="n">std</span><span class="o">::</span><span class="n">system</span><span class="p">(</span> <span class="n">s</span><span class="p">.</span><span class="n">c_str</span><span class="p">()</span> <span class="p">)</span> <span class="p">)</span> <span class="k">return</span> <span class="mi">1</span><span class="p">;</span> <span class="p">}</span> <span class="k">else</span><span class="p">{</span> <span class="n">CoInitializeEx</span><span class="p">(</span><span class="nb">NULL</span><span class="p">,</span> <span class="n">COINIT_MULTITHREADED</span> <span class="p">);</span> <span class="c1">//***********</span> <span class="n">co_uninitializer</span> <span class="n">co_uninit</span><span class="p">;</span> <span class="c1">//***********</span> <span class="c1">//Open already created shared memory object.</span> <span class="n">shared_memory_object</span> <span class="n">shm</span> <span class="p">(</span><span class="n">open_only</span><span class="p">,</span> <span class="s">&quot;MySharedMemory&quot;</span><span class="p">,</span> <span class="n">read_only</span><span class="p">);</span> <span class="c1">//Map the whole shared memory in this process</span> <span class="n">mapped_region</span> <span class="n">region</span><span class="p">(</span><span class="n">shm</span><span class="p">,</span> <span class="n">read_only</span><span class="p">);</span> <span class="c1">//Check that memory was initialized to 1</span> <span class="kt">char</span> <span class="o">*</span><span class="n">mem</span> <span class="o">=</span> <span class="k">static_cast</span><span class="o">&lt;</span><span class="kt">char</span><span class="o">*&gt;</span><span class="p">(</span><span class="n">region</span><span class="p">.</span><span class="n">get_address</span><span class="p">());</span> <span class="k">for</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="kt">size_t</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">region</span><span class="p">.</span><span class="n">get_size</span><span class="p">();</span> <span class="o">++</span><span class="n">i</span><span class="p">)</span> <span class="k">if</span><span class="p">(</span><span class="o">*</span><span class="n">mem</span><span class="o">++</span> <span class="o">!=</span> <span class="mi">1</span><span class="p">)</span> <span class="k">return</span> <span class="mi">1</span><span class="p">;</span> <span class="c1">//Error checking memory</span> <span class="p">}</span> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> <span class="p">}</span> </pre></div></div></div><p> The problem seems to be fixed by modifying get_wmi_class_attribute() in interprocess/detail/win32_api.hpp in the following way: </p> <div class="wikipage" style="font-size: 80%"><div class="wiki-code"><div class="code"><pre><span class="c1">// ...</span> <span class="k">const</span> <span class="kt">signed</span> <span class="kt">long</span> <span class="n">RPC_E_CHANGED_MODE_BIPC</span> <span class="o">=</span> <span class="mh">0x80010106L</span><span class="p">;</span> <span class="c1">// ...</span> <span class="kr">inline</span> <span class="kt">bool</span> <span class="nf">get_wmi_class_attribute</span><span class="p">(</span> <span class="n">std</span><span class="o">::</span><span class="n">wstring</span><span class="o">&amp;</span> <span class="n">strValue</span><span class="p">,</span> <span class="k">const</span> <span class="kt">wchar_t</span> <span class="o">*</span><span class="n">wmi_class</span><span class="p">,</span> <span class="k">const</span> <span class="kt">wchar_t</span> <span class="o">*</span><span class="n">wmi_class_var</span><span class="p">)</span> <span class="p">{</span> <span class="c1">//See example http://msdn.microsoft.com/en-us/library/aa390423%28v=VS.85%29.aspx</span> <span class="kt">long</span> <span class="n">co_init_ret</span> <span class="o">=</span> <span class="n">CoInitialize</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span> <span class="k">if</span><span class="p">(</span><span class="n">co_init_ret</span> <span class="o">!=</span> <span class="n">S_OK_BIPC</span> <span class="o">&amp;&amp;</span> <span class="n">co_init_ret</span> <span class="o">!=</span> <span class="n">S_FALSE_BIPC</span> <span class="o">&amp;&amp;</span> <span class="n">co_init_ret</span> <span class="o">!=</span> <span class="n">RPC_E_CHANGED_MODE_BIPC</span> <span class="p">)</span> <span class="k">return</span> <span class="nb">false</span><span class="p">;</span> <span class="c1">// Uninitialize COM at function exit if not already initialized with different threading model</span> <span class="n">std</span><span class="o">::</span><span class="n">auto_ptr</span><span class="o">&lt;</span><span class="n">co_uninitializer</span><span class="o">&gt;</span> <span class="n">co_initialize_end</span><span class="p">((</span> <span class="n">co_init_ret</span> <span class="o">!=</span> <span class="n">RPC_E_CHANGED_MODE_BIPC</span> <span class="p">)</span> <span class="o">?</span> <span class="k">new</span> <span class="nl">co_uninitializer</span> <span class="p">:</span> <span class="p">(</span><span class="n">co_uninitializer</span><span class="o">*</span><span class="p">)</span><span class="mi">0</span> <span class="p">);</span> <span class="kt">bool</span> <span class="n">bRet</span> <span class="o">=</span> <span class="nb">false</span><span class="p">;</span> <span class="c1">// ...</span> </pre></div></div></div> en-us Boost C++ Libraries /htdocs/site/boost.png https://svn.boost.org/trac10/ticket/7152 Trac 1.4.3 Ion Gaztañaga Thu, 19 Jul 2012 21:01:24 GMT status changed; resolution set https://svn.boost.org/trac10/ticket/7152#comment:1 https://svn.boost.org/trac10/ticket/7152#comment:1 <ul> <li><strong>status</strong> <span class="trac-field-old">new</span> → <span class="trac-field-new">closed</span> </li> <li><strong>resolution</strong> → <span class="trac-field-new">fixed</span> </li> </ul> <p> Thanks for the report, fixed in revisions 79609 and 79610 in release branch and 79611 &amp; 79612 in trunk. </p> <p> <a class="missing wiki">CoInitializeEx</a> is used and a macro to select the initialization mode for Interprocess is also provided. See documentation notes and win32_api.hpp for more details. </p> Ticket