1

I'm using a Boost based shared vector as IPC in my application.

In the application where I'm trying to read the shared memory, the size of the memory, m_size, or vector->size, keeps fluctuating between 2 ( i.e. the number of vectors I'm sharing ),and 0. I've no idea why this is happening. Maybe it's a synchronization issue? But even if this is the case, the size of the memory should not come to 0, as it's just reading whatever is there in the memory. It may be invalid ( i.e. old data ), but not 0.

Also, the application which writes to the shared memory repeatedly outputs 2, as the size of the shared memory...

What could be the error?

This creates additional problems, as I'm using the size of the shared memory to see if anything's been written inside it. If that is not correct, what other parameter can I use for it?

Kindly advise.

Thank you.

EDIT :

Application which Writes :

Creation

    shared_memory_object::remove("MySharedMemory");   // CREATION
m_bIsConnectionActive = false;
srvConnections = new PwServerCheckClass();

managed_shared_memory segment(create_only, "MySharedMemory", 65536);

const ShmemAllocator alloc_inst (segment.get_segment_manager());
vector_to_send = segment.construct<VECTOR_TO_SEND>("VECTOR_TO_SEND")(alloc_inst);

And now writing

    m_vector_to_send = srvConnections->getServerList();  //Vector whose contents are to be copied into shared vector
for(UINT loopCounter = 0; loopCounter < m_vector_to_send.size(); loopCounter++)
{
        SERVER_INFO_TYPE_CHAR TestSrv;
                    <Some code>
        vector_to_send->push_back(TestSrv); //Pushing vector back into shared memory
        wcout<<endl<<"Size of the vector is::"<<vector_to_send->size();

}

Application which reads :

Reading :

    managed_shared_memory segment(open_only, "MySharedMemory");
m_serverVector = segment.find<VECTOR_TO_SEND>("VECTOR_TO_SEND").first;
//int checkSrvSize = m_serverVector->shrink_to_fit;
if(m_serverVector == NULL)
    return;
int SrvSizeCheck = 1;
do
{
    if(!(m_serverVector->empty()))
        continue;
           for(auto it = m_serverVector->begin() ; it != m_serverVector->end() ; ++it, ++SrvSizeCheck)
           <Some code>

Here is where the behaviour becomes odd. Sometimes the vector->empty() is satisfied, though something is being written into the memory. Sometimes it goes past the empty() check and instead fails at the it != m_serverVector->end() condition. I don't know what to make out of it.

EDIT 2

I took a look at the documentation. According to it, for the semaphore section, the actual mutex is associated with the shared memory. So a struct is created, there is an array inside it, and some sempahores. And eventually it is this structure which is shared in memory.

In my case, I'm sharing a vector in shared memory. Would the same principle work, i.e. I create a structure with a vector inside it, alongwith the mutex members, and share it across? In this case, the structure to be mapped, and consequently the memory allocator, would be that of the struct and not that of the Vector, as I've done in my code, correct?

Kindly advise.

user1173240
  • 1,455
  • 2
  • 23
  • 50
  • There is no code. How can we know what's correct? [Seems reasonable](http://coliru.stacked-crooked.com/a/0099246924698d7c). Also, what even _is_ the size of the shared memory (hint: it's fixed unless you call `grow()` which cannot be used concurrently). – sehe Apr 01 '14 at 06:49
  • I've added some code. Kindly advise. – user1173240 Apr 01 '14 at 07:13

1 Answers1

1

Yes, you don't seem to have any locking in place.

Sharing memory between processes risks concurrent mutation/access. For this you need locking. Otherwise you introduce a data race and this invokes Undefined Behaviour as per the c++ standard.

In fact - in most real-life situations you'd actually need a mutex locking the creation of the shared memory area (unless you can prove that the creation is single-threaded).

Look at

If you want, you can use a semaphore to have an efficient message queue with 'message ready' notification. See BIP Semaphore

Finally, you can use lock-free access iff you use a lockfree container specifically designed for this, e.g. Shared-memory IPC synchronization (lock-free)

Community
  • 1
  • 1
sehe
  • 374,641
  • 47
  • 450
  • 633
  • I just have 2 processes - One which creates it only once and starts writing stuff into it, and another which just reads it. So, when the second process starts reading, do I need a Mutex even for that? With reading, I/m not manipulating anything, so how come a race condition can occur? And what's the relation between that and the size fluctuating? – user1173240 Apr 01 '14 at 08:37
  • If the first process can modify, then of course you need locking before reading (imagine detecting `size()==1` and then indirecting `v[0]` but in the mean time the vector has been reallocated/resized) – sehe Apr 01 '14 at 08:41
  • 1
    The relation between Undefined Behaviour and "the size fluctuating" is precisely the same relation as between Undefined Behaviour and ["daemons flying out of your nose"](http://www.catb.org/jargon/html/N/nasal-demons.html) – sehe Apr 01 '14 at 08:42
  • @sehe If you have a computer than that can _actually_ result in daemons flying out of my nose, then you should be monumentally rich by now. – Lightness Races in Orbit Apr 01 '14 at 08:43
  • @LightnessRacesinOrbit probabilities do not detract anything for the equivalence of the relations, in principle – sehe Apr 01 '14 at 08:44
  • ... in the same way. Did you add synchronization? If not, you can stop trying – sehe Apr 01 '14 at 09:15
  • mm...I allocated some size to the vector..OK. Now the first process is writing to it. How are subsequent writes to that shared memory done? Does it delete the content first, and then write to it again, or does it write on top of it ( in which case, nothing's been resized or reallocated, so size shouldn't come as 0)...I'm just asking as the write mechanism and what happens internally isn't very clear to me. – user1173240 Apr 01 '14 at 09:17
  • Shared memory is just... memory. You write to it as you've always done. And the results are visible to the other processes immediately (because it's just that... shared memory). This is also why you need synchronization. It's basically like having threads but with (a) process isolation (b) a whole lot more complicated due to requiring specialized allocators and OS specific memory mapping incantations :) – sehe Apr 01 '14 at 09:19
  • mm..OK. I probably got the answer to why it was 0. Just before writing to the shared memory, I used to erase it, so the shared memory wouldn't accumulate in size. I suppose when the reader accessed it during this phase, it got the size 0 treatment. So I suppose it does need synchronization. Thank you very much for your help on this. – user1173240 Apr 01 '14 at 10:04
  • I've added another question for clarification. Kindly advise. – user1173240 Apr 02 '14 at 07:56