2

I'm writing an application, for learning purposes, that is composed of two executables. Among other things, each executable creates a shared memory segment of his own (with different keys), after that executable A tries to create a segment using B's key, and B does the same with A's key (the purpose of this is for each executable to check if the other is still running. I know that this probably isnt the best way of accomplishing this but i ask you to not focus on this fact). If either program succeeds in creating a segment with the other's key, it assumes the other is not running and takes action accordingly.

The problem that happens is that this works OK when B checks A. But when A checks B, it can create a segment with the same key B has already created. I'm pretty sure i checked all race conditions possible, and im also pretty sure that both segments exist at the same time with the same key (both QSharedMemory create calls with this key return true). In fact, just for giggles, i've placed the create call inside a loop and it can keep creating the segment with the same key for as long as the loop goes. I tried passing the key directly in the constructor, using setKey() and using setNativeKey() and none worked.

And as said before, what really boggles my mind is that the same approach works for B checking A, but not the other way around.

I dont know why this is happening? Does the key have to follow any standards? Does QSharedMemory have a restriction or specific behavior when being used inside a thread/signal/method?

A's code snipet (method is called using signals - DOES NOT WORK):

//Process A "signature" creation
QSharedMemory process_a_signature("61BB200D-3579-453e-9044-");
if(process_a_signature.create(512,QSharedMemory::ReadWrite)==true) {
    qDebug() << "Process A signature created.";
} else exit(0);

...

//Method that checks for process B (monitor)
void LaRunTime::checkMonitorProcess(){


QSharedMemory monitorsignature("61BB201D-3569-453e-9144-");
if(monitorsignature.create(512,QSharedMemory::ReadWrite)==true) {
    qDebug() << "Process B is not running.";
} else {
    qDebug() << "Process B is running.";
}

B's code snippet (method is also called using signals - WORKS)

//Process B "signature" creation
QSharedMemory monitorsignature("61BB201D-3569-453e-9144-");
if(monitorsignature.create(512,QSharedMemory::ReadWrite)==true) {
    qDebug() << "Process B signature created.";
} else {
    exit(0);
}

...

//Method that checks for process A
void LaClientMonitor::checkProcess(){

QSharedMemory process_a_signature("61BB200D-3579-453e-9044-");
if(process_a_signature.create(512,QSharedMemory::ReadWrite)==true) {
    qDebug() << "Process A is not running.";
} else {
    qDebug() << "Process A is running.";
}
  • Is the aim to identify during startup whether some initialization needs to be done (because the other process hasn't done it), or is the aim to be notified during runtime if the other process stops running? – John Zwinck Dec 20 '15 at 06:25
  • The aim is to notify during runtime if the other process stops running. – Luis Carlos Jersak Dec 20 '15 at 16:07
  • Would you consider using a simple TCP connection between them for that? I think it is simpler and reliable. – John Zwinck Dec 20 '15 at 16:14
  • Actually yes, but with an UDP connection. It turned out to be unreliable for some reason. Do you think a TCP connection would be better? Also, i asked here more because im curious on what is happening than because of the problem itself. – Luis Carlos Jersak Dec 20 '15 at 16:36
  • UDP does not have connections. You should use TCP with keep-alive enabled. – John Zwinck Dec 21 '15 at 03:16

1 Answers1

1

So, after fiddling with the code in a few other ocasions i found out that the problem was happening because i was creating the shared memory segment inside a class / object, and for some reason (i believe related to the life cycle of the object) it was being destroyed right after its creation. Moving the code that creates the memory segment to main.cpp file solved the problem.