Ticket #7152 (closed Bugs: fixed)

Opened 4 years ago

Last modified 4 years ago

Interprocess 1.50 windows_bootstamp fails when COM already initialized in multithreaded

Reported by: Charles Savoie <boost@…> Owned by: igaztanaga
Milestone: To Be Determined Component: interprocess
Version: Boost 1.50.0 Severity: Problem
Keywords: windows bootstamp tmpfile tempfile shared memory shm Cc:


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 CoInitialize?(0) and failing to test for RPC_E_CHANGED_MODE.

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.

A slight modification to the example program in the shared memory documentation ( displays the problem:

#include <boost/interprocess/shared_memory_object.hpp>
#include <boost/interprocess/mapped_region.hpp>
#include <cstring>
#include <cstdlib>
#include <string>

#include <atlbase.h>

struct co_uninitializer{ ~co_uninitializer() { CoUninitialize(); } };

int main(int argc, char *argv[])
    using namespace boost::interprocess;

    if(argc == 1){  //Parent process

        //Remove shared memory on construction and destruction
        struct shm_remove
            shm_remove() { shared_memory_object::remove("MySharedMemory"); }
            ~shm_remove(){ shared_memory_object::remove("MySharedMemory"); }
        } remover;

        //Create a shared memory object.
        shared_memory_object shm (create_only, "MySharedMemory", read_write);

        //Set size

        //Map the whole shared memory in this process
        mapped_region region(shm, read_write);

        //Write all the memory to 1
        std::memset(region.get_address(), 1, region.get_size());

        //Launch child process
        std::string s(argv[0]);
        s = "\"" + s + "\"" + " child ";

        if(0 != std::system( s.c_str() ) )
            return 1;

        CoInitializeEx(NULL, COINIT_MULTITHREADED );  //***********
        co_uninitializer co_uninit;                   //***********

        //Open already created shared memory object.
        shared_memory_object shm (open_only, "MySharedMemory", read_only);

        //Map the whole shared memory in this process
        mapped_region region(shm, read_only);

        //Check that memory was initialized to 1
        char *mem = static_cast<char*>(region.get_address());
        for(std::size_t i = 0; i < region.get_size(); ++i)
            if(*mem++ != 1)
                return 1;   //Error checking memory
    return 0;

The problem seems to be fixed by modifying get_wmi_class_attribute() in interprocess/detail/win32_api.hpp in the following way:

// ...
const   signed long RPC_E_CHANGED_MODE_BIPC = 0x80010106L;
// ...

inline bool get_wmi_class_attribute( std::wstring& strValue, const wchar_t *wmi_class, const wchar_t *wmi_class_var)
   //See example
   long co_init_ret = CoInitialize(0);
   if(co_init_ret != S_OK_BIPC && co_init_ret != S_FALSE_BIPC && co_init_ret != RPC_E_CHANGED_MODE_BIPC )
      return false;

   // Uninitialize COM at function exit if not already initialized with different threading model
   std::auto_ptr<co_uninitializer> co_initialize_end(( co_init_ret != RPC_E_CHANGED_MODE_BIPC ) ? new co_uninitializer : (co_uninitializer*)0 );

   bool bRet = false;
   // ...


Change History

comment:1 Changed 4 years ago by igaztanaga

  • Status changed from new to closed
  • Resolution set to fixed

Thanks for the report, fixed in revisions 79609 and 79610 in release branch and 79611 & 79612 in trunk.

CoInitializeEx? 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.


Add a comment

Modify Ticket

Change Properties
<Author field>
as closed
The resolution will be deleted. Next status will be 'reopened'

E-mail address and user name can be saved in the Preferences.

Note: See TracTickets for help on using tickets.