Opened 10 years ago

Last modified 7 years ago

#8276 new Bugs

Shared Memory Access by 32-bit and 64-bit Processes

Reported by: Bob Stevens <bob@…> Owned by: Ion Gaztañaga
Milestone: To Be Determined Component: interprocess
Version: Boost 1.52.0 Severity: Showstopper
Keywords: 32Bit, 64Bit Cc:

Description

Problem: Exception raised in Segment.find_or_construct<>() call.

Problem: Exception raised in Segment.find_or_construct<>() call.

The system operates if all of the the processes are 64-bit, or if all of the processes are 32-bit.

If the shared memory segment has been constructed by a 64-bit process, attempting to find_or_construct it with a 32-bit process fails.  Similary, if the shared memory segment has been constructed by a 32-bit process, attempting to find_of_construct it with a 64-bit process fails.

I have determined that the actual objects in shared memory report different sizes when compiled for 32-bit or 64-bit.

This is a multi-cast PubSub program.  It constructs the following complex data structure in shared memory:

    // Boost includes
    #include <boost\interprocess\managed_shared_memory.hpp>
    #include <boost\interprocess\containers\map.hpp>
    #include <boost\unordered_map.hpp>
    #include <boost\interprocess\allocators\allocator.hpp>
    #include <boost\interprocess\containers\vector.hpp>
    #include <boost\interprocess\containers\string.hpp>
    #include <boost\interprocess\sync\interprocess_mutex.hpp>
    #include <boost\interprocess\sync\interprocess_semaphore.hpp>
    #include <boost\interprocess\sync\scoped_lock.hpp>
    #include <boost\interprocess\detail\move.hpp>
    #include <boost\thread.hpp>
    #include <boost\foreach.hpp>
    #include <boost\format.hpp>
    #include <functional>
    #include <boost/functional/hash.hpp>

    typedef managed_shared_memory::segment_manager          segment_manager_t;      // this is the segment_manager

    // Define the allocators.
    typedef boost::interprocess::allocator<void, segment_manager_t>              void_allocator;         // void_allocator is convertible to any other allocator<T>.
    typedef boost::interprocess::allocator<int, segment_manager_t>               int_allocator;          // allocator for allocating ints.
    typedef boost::interprocess::vector<int, int_allocator>                      int_vector;             // an int_vector is a vector of ints.
    typedef boost::interprocess::allocator<int_vector, segment_manager_t>        int_vector_allocator;   // an allocator for allocating vectors of ints.
    typedef boost::interprocess::vector<int_vector, int_vector_allocator>        int_vector_vector;      // an int_vector_vector is a vecctor of (vectors of ints)
    typedef boost::interprocess::allocator<interprocess_semaphore, segment_manager_t>  semaphore_allocator;   // an allocator for interprocess_semaphore
    typedef boost::interprocess::allocator<WCHAR, segment_manager_t>             wchar_allocator;        // an allocator for wide chars.
    typedef boost::interprocess::basic_string<WCHAR, std::char_traits<WCHAR>, wchar_allocator>  wchar_string;  // a basic_string (which supports formatting).  This is built on a collection of wide chars, allocated by wchar_alloctor.

    class EventMessage {
        EnumEventType EventType_;           // an enum
        EnumEventSubType EventSubType;      // an enum
        ULONG32 ProcessId_;
        ULONG32 ThreadId_;
        EnumMyType MyType_;                 // an enum
        wchar_string FullPath_;
        GUID GuidPublisher_;
    }

    // Event allocators
    typedef boost::interprocess::allocator<EventMessage, segment_manager_t>     EventMessage_allocator;         // allocator for allocating EventMessage
    typedef boost::interprocess::vector<EventMessage, EventMessage_allocator>   EventMessage_vector;            // vector of EventMessage objects.

    class Subscription {
        ULONG32 uSignature_;
        ULONG32 uSubscribingProcessId_;
        ULONG32 uSubscribingThreadId_;
        EnumEventType nEventType_           // an enum
        offset_ptr<interprocess_semaphore> pSemaphoreSubscription_;
        GUID guidSubscriber_;
        BOOL fDestructed;
        BOOL fWaiting_;
        BOOL fCancelled_;
        EventMessage_vector events_;    // a shared memory vector of EventMessage
    }

    // Define the types related to Subscription
    typedef boost::interprocess::allocator<Subscription, segment_manager_t>                      subscription_allocator;     // allocator for allocating Subscription
    typedef boost::interprocess::allocator<GUID, segment_manager_t>                             guid_allocator;         // allocator for allocating GUID
    typedef std::pair<const GUID, Subscription>                                                 pair_guid_subscription; // a pair of GUID, Subscription
    typedef boost::interprocess::allocator<EnumEventType, segment_manager_t>                    eventtype_allocator;    // allocator for allocating EnumEventType
    typedef boost::interprocess::allocator<pair_guid_subscription, segment_manager_t>           pair_guid_subscription_allocator;  // allocator for pair_guid_subscription
    typedef boost::unordered_map<GUID, Subscription, boost::hash<GUID>, std::equal_to<GUID>, pair_guid_subscription_allocator>  guid_subscription_map;  // a map of GUID => Subscription
    typedef std::pair<const EnumEventType, guid_subscription_map>                               pair_eventtype_pair_guid_subscription;  // a pair(EnumEventType, pair(GUID, Subscription))
    typedef boost::interprocess::allocator<pair_eventtype_pair_guid_subscription, segment_manager_t>  pair_eventtype_pair_guid_subscription_allocator;  // allocator for pair(EnumEventType, pair(GUID, Subscription))
    typedef boost::unordered_map<EnumEventType, guid_subscription_map, boost::hash<int>, std::equal_to<int>, pair_eventtype_pair_guid_subscription_allocator> eventtype_map_guid_subscription_map;  // a map(EnumEventType, map<GUID, Subscription)>
    typedef boost::interprocess::vector<Subscription, subscription_allocator>                    subscription_vector;    // a vector of Subscriptions
    typedef boost::interprocess::allocator<subscription_vector, segment_manager_t>               subscription_vector_allocator;  // allocator for allocating a vector of Subscription.
    typedef boost::interprocess::allocator<guid_subscription_map, segment_manager_t>            guid_subscription_map_allocator;  // allocator for allocating a map of GUID => Subscription
    typedef boost::interprocess::allocator<eventtype_map_guid_subscription_map, segment_manager_t> eventtype_map_guid_subscription_map_allocator;  // allocator for allocating map<EnumEventType, map<GUID, Subscription>>

    // This is the single item defined in the segment
    class Base {
        uint64_t reserved1_;
        uint64_t reserved2_;
        ULONG32 uSignature_;
        interprocess_mutex  mutexSharedMemory_
        eventtype_map_guid_subscription_map subscriptions_;  // a shared memory map of [GUID, Subscription] (the active subscriptions)
    }

The following sizes are reported:
64-bit
    sizeof(IntPtr): 8
    sizeof(ULONG32): 4
    sizeof(BOOL): 4
    sizeof(EnumEventType): 4
    sizeof(EnumEventSubType): 4
    sizeof(EnumCloudAppIconBadgeType): 4
    sizeof(GUID): 16
    sizeof(EventMessage): 72
    sizeof(Subscription): 88
    sizeof(Base): 104
    sizeof(size_t): 8

32-bit:
    sizeof(IntPtr): 4
    sizeof(ULONG32): 4
    sizeof(BOOL): 4
    sizeof(EnumEventType): 4
    sizeof(EnumEventSubType): 4
    sizeof(EnumCloudAppIconBadgeType): 4
    sizeof(GUID): 16
    sizeof(EventMessage): 60
    sizeof(Subscription): 64
    sizeof(Base): 72
    sizeof(size_t): 4

Note that all of the fundamental types are the same size, but the Boost interprocess sizes are different.

I thought that as of Boost 1.48 all of the sizes were normalized to use the same shared memory sizes whether compiled for 32- or 64-bit.

Perhaps I am doing something wrong.  Suggestions will be welcome.  Thanks.

Change History (1)

comment:1 by ingmar.koecher@…, 7 years ago

I'm having a similar issue in Boost 1.57 that I believe is related. A boost vector created in shared memory inside a 64-bit process cannot be "found" in a 32-bit process. It works correctly if both processes are 32-bit.

While the shared memory can be opened, the object inside cannot be found.

Note: See TracTickets for help on using tickets.