Re: [Boost-users] Interprocess container segmentation fault (example provided)
Ion,
Terribly sorry, but I goofed when I cobbled that code together. My actual application constructs "TestStore" from the segment, and not on the stack like what I pasted in before. I'm including the full test code again, although only the main function changed. Since the map itself a member of TestStore and TestStore is being constructed from the segment, I would think that should be roughly equivalent to just creating the map by itself from the segment. However, as you'll see if you run it, it still seg faults when accessing the list iterator.
===================================== BEGIN CODE==============================================
#include
I'm running into issues with using interprocess containers have other containers added to them during runtime. A very high level description is I have a set of data structures in shared memory that can be accessed and modified by more than one process. I'm creating the data structures in the first process and storing the name of the segment within the data structure. Methods that modify the data by adding another container first lookup the segment using its name, build the new container, and then insert it into the existing container. In the example I'm providing below, I have a map of lists. For some reason, when I add a new list, if I open the segment by name, and allocate the list using the segment manager returned via the lookup, the list isn't initialized correctly and accessing the list (via printData here) results in a segfault. However, if I bypass the segment lookup and just cache the raw pointer to the segment, it works. It's probably easiest just to look at the code below. In addMessage, you can see how I'm trying to initialize the list in a manner that will work across multiple processes. This breaks. Commented out directly below it is a hack that will work. I can't see any reason why one works and the other doesn't. The "managed_shared_memory" object returned from the lookup appears to be valid and exactly the same as the pointer I'm caching with the data structure in this example.
I am currently using 1.49 final, but I've observed similar behavior in other 1.4x releases.
You are storing a *local* map that allocates memory in shared memory (that is, the internal pointers of the map are in the stack, whereas the allocated nodes are in shared memory), which is really a bad idea as once you unmap the segment, as the local map's internal pointers point to segmentation-fault friendly memory. I know that "managed_shared_memory shm" outlives "TestStore store" but the problem is that you open the shm again in "managed_shared_memory m" and that maps the shared memory *in another address, different to the address mapped by "managed_shared_memory shm"* (two views of the same shared memory, as you map a file twice). So you end up with a local map pointing to *two different address ranges* (although the share the same underlying shared memory object, just think it's like a file). Then you unmap "managed_shared_memory m" (the second address range disappears) and then when you try to iterate, when the local map tries to read an element through the second address range, you get a segmentation fault. If you put the map itself in shared memory (e.g. use a named construct) you can avoid the problem. And if you have already mapped the shared memory once, avoid wasting OS resources (the OS must synchronize the two address ranges in the same process with the same underlying device/shm/mapped file) and application address space mapping the same shared memory/file several times. Sometimes is useful to open the shared memory segment more than once from the same process (say, when you communicate a DLL with an application, or when trying to implement a intermodule singleton type), but in general, try to avoid this. Best, Ion _______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
Josh --
"Davidson, Josh"
Since the map itself a member of TestStore and TestStore is being constructed from the segment, I would think that should be roughly equivalent to just creating the map by itself from the segment. However, as you'll see if you run it, it still seg faults when accessing the list iterator.
I believe that Ion's comments about the use of 'm' in
TestStore::addMessage are still correct and are near the root of the
problem.
I'd recommend arranging your class so that successful construction
implies:
1. the named shared segment itself has been found or created and
mapped;
2. the named object within the segment has been found or created;
3. the object is in a valid state and ready for operations.
Additionally, you should treat this as a Singleton within each process
(to avoid the multiple-mapping problems that Ion mentioned). You can
do that with simple discipline / review, or you can force it by hiding
it behind a factory method, employing "boost::noncopyable", etc.
This means that your "addMessage" method will always have exactly the
correct segment manager to allocate additional resources.
I wrote a very similar container, although it only mapped strings to
strings:
http://scrye.com/~tkil/cpp/boost-interprocess/SharedMap.hpp
http://scrye.com/~tkil/cpp/boost-interprocess/SharedMap.cpp
http://scrye.com/~tkil/cpp/boost-interprocess/SharedMapTest.cpp
(The test won't compile, as it relies on other classes from the
original codebase; but it should show you how the SharedMap class is
intended to be used.)
I also wrote a few replies on the list, a month or two back, that
touch on these same topics:
http://groups.google.com/group/boost-list/msg/ee619a75277b2146
My version of your code follows; it is also available at:
http://scrye.com/~tkil/cpp/boost-interprocess/josh-shared-data.cpp
The main changes are:
a. Make all the typedefs private to the class; they're an
implementation detail.
b. Have the class do all the work of lookup, mapping, and allocation;
this makes for a much simpler interface.
c. Minor issues: within the class, there is only one Map, List, and
Datum type, so remove some of the very long prefixes.
And a few other bits. Hopefully you'll find this useful.
Best regards,
Anthony Foiani
========================================================================
// linux compile line:
// g++ -O2 -o josh-shared-data josh-shared-data.cpp -lpthread -lrt
#include
participants (2)
-
Anthony Foiani
-
Davidson, Josh