[interprocess] access dynamically accessed shared region in another process
Hi there, I'm trying to do IPC via boost.interprocess and use a dynamic buffer. This is on windows, debug mt, boost 1.38. To do this, I first create a shared segment and then a dynamic area in it. like this: struct transfer_buffer { void *buf; size_t bufsize; boost::interprocess::interprocess_mutex mutex; size_t dmember; } typedef boost::interprocess::managed_windows_shared_memory shared_segment; ... using namespace boost::interprocess; shared_memory_object::remove(bufname); struct transfer_buffer *ret = 0; shared_segment_ptr seg;// I use a ptr to store the object away so it won't get lost seg.reset(new shared_segment(create_only, bufname, begin_size)); // and our maintanance struct in it ret = seg->construct<struct transfer_buffer>(unique_instance)(); ret->dmember = 42; const std::size_t Alignment = 128; ret->bufsize = 1982781; ret->buf = seg->allocate_aligned(ret->bufsize, Alignment); Then, process A writes into the dynamic buffer, which seems to work OK. In the other process however, I try to open it and read the data. Like this: seg.reset(new shared_segment(open_only, bufname)); ret = seg->find<struct transfer_buffer>(unique_instance).first; Now I can access everything fine in ret (the struct itself), including the mutex and data members. But I cannot access the dynamically allocated buffer. As soon as I access it (read it, memcpy, anything) the app crashes with what would appear to be a rather broken callstack. When I look at the transfer_buffer struct before the crash it looks as if the dynamic pointer points to some inaccessable area. Not what I wrote in it anyway. Do I have to do anything else (other than creating the segment and find() the unique transfer_buffer struct) in the other process to access the dynamic area? Or is this a bug? Any help appreciated... Stephan
To do this, I first create a shared segment and then a dynamic area in it. like this:
struct transfer_buffer { void *buf; size_t bufsize; boost::interprocess::interprocess_mutex mutex; size_t dmember; }
I only quickly looked at your code, but I think that your void* pointer is invalid in the second process. Take a look at boost::interprocess::offset_ptr and use it in place of void*. ~Dan
Casimiro, Daniel C CIV NUWC NWPT wrote:
To do this, I first create a shared segment and then a dynamic area in it. like this:
struct transfer_buffer { void *buf; size_t bufsize; boost::interprocess::interprocess_mutex mutex; size_t dmember; }
I only quickly looked at your code, but I think that your void* pointer is invalid in the second process.
Take a look at boost::interprocess::offset_ptr and use it in place of void*.
~Dan
Thanks for the quick reply, Dan. Yes, all pointers placed in shared memory should be offset_ptr as explained here: http://www.boost.org/doc/libs/1_38_0/doc/html/interprocess/sharedmemorybetwe... Regards, Ion
Am Mittwoch, 1. April 2009 18:58:39 schrieb Ion Gaztañaga:
Thanks for the quick reply, Dan. Yes, all pointers placed in shared memory should be offset_ptr as explained here:
http://www.boost.org/doc/libs/1_38_0/doc/html/interprocess/sharedmemorybetw eenprocesses.html#interprocess.sharedmemorybetweenprocesses.mapped_region_ob ject_limitations
Thanks for the quick reply! Meanwhile I suspected as much, but didn't know for sure how to interpret the docs. Also, this alignment check taken from the docs doesn't compile anymore with a pointer type as such: struct transfer_buffer { boost::interprocess::offset_ptr<void> buf; size_t bufsize; }; ... ret->bufsize = SIZE; ret->buf = seg->allocate_aligned(ret->bufsize, Alignment); // Check alignment assert((static_cast<void *>(ret->buf) - static_cast<void *>(0)) % Alignment == 0); The assert gives me: /home/sm/devel/rtssvn/cpp/librender/Render.cpp:109: Erro: invalid static_cast of type »boost::interprocess::offset_ptr<void>« into type »void*« Is that assert actually neccessary? I wouldn't know what to do in case of a failure anyway.... Performance accessing the buffer matters a lot though. Cheers, Stephan
Meanwhile I suspected as much, but didn't know for sure how to interpret the docs. Also, this alignment check taken from the docs doesn't compile anymore with a pointer type as such:
struct transfer_buffer { boost::interprocess::offset_ptr<void> buf; size_t bufsize; }; ... ret->bufsize = SIZE; ret->buf = seg->allocate_aligned(ret->bufsize, Alignment);
// Check alignment assert((static_cast<void *>(ret->buf) - static_cast<void *>(0)) % Alignment == 0);
Obviously, offset_ptr is not a pointer so it can be static_cast'ed. offset_ptr is a smart pointer that emulates a pointer that can be placed in shared memory. See offset_ptr docs and implementation for more details. Try // Check alignment assert((static_cast<void *>(ret->buf.get()) - static_cast<void *>(0)) % Alignment ==
0);
Regards, Ion
Am Mittwoch, 1. April 2009 21:13:33 schrieb Ion Gaztañaga:
// Check alignment assert((static_cast<void *>(ret->buf) - static_cast<void *>(0)) % Alignment == 0);
Obviously, offset_ptr is not a pointer so it can be static_cast'ed. offset_ptr is a smart pointer that emulates a pointer that can be placed in shared memory. See offset_ptr docs and implementation for more details. Try
// Check alignment assert((static_cast<void *>(ret->buf.get()) - static_cast<void *>(0)) % Alignment == 0);
Indeed. That was what I tried first. But that doesn't work either: The compiler says "invalid use of »void«" However, this does: assert((static_cast<char *>(ret->buf.get()) - static_cast<char *>(0)) % Alignment == 0); The pointer arithmetics need char*. So everything is fine. Thanks a bunch for your help with that great library! Cheers, Stephan
participants (3)
-
Casimiro, Daniel C CIV NUWC NWPT
-
Ion Gaztañaga
-
Stephan Menzel