[Solved] Synchronisation between processes



  • Hi People,

    my problem is the following:
    We have two process which operate on same shared memory area (QSharedMemory instance), but they are need to syncronise theirs operations (initialise the shared memory). I had tried to use the QSystemSemaphore, but it doesn't work for me. The parent process acquire it and the child process doesn't able to acquire the semaphore.
    I think: it is may a good sollution when I can check the acquired item count, or I can call some "try"acquire not only acquire.

    Other example: in .NET exist an eventwait handle or system wide mutex.

    Can someone tell me an pretty solution?

    Thank you!
    Regards,
    Norbert



  • Have you tried QSharedMemory lock/unlock method? It simulates mutex behaviour, blocks and waits until memory segment is available (it means is unlocked).
    I'm surprised that QSystemSemaphore doesn't work for you. Could you provide kind of example how you use it?



  • Hy,

    the main problem with the "lock" like methods that they are not handlet priority, they blocks the caller until theresource is locked: imagine the situation: "A" process have to lock every time the sahred memory, mutex, QSystemSemaphore, or other resource, but "B" process have only right to try locking the resource.
    Sorry, but I don't check in the sources so I don't provide for you those :(

    Regards,
    Norbert



  • I understand that you need try-lock inter-process mutex, right? Unfortunately I don't see such thing in Qt.
    You could emulate such feature, for example by checking file existence (process A checks some file existence periodically, and B creates such file if memory is ready) or by any other way exchanging such information between your processes.
    You could also use boost.interprocess named_mutex. It's global mutex, contains try_lock method, and it's not connected with shared-memory so you can still use QSharedMemory if you want.



  • Hi Bogdan,

    thank you for your replies!
    Yes, you undersatnd right.
    The "shared file" seems to goog idea, but I think it is slower as communication via an memory area. In this case is it an appropiable solution.
    I solved the problem, but I have an interest idea: a QMutex object on a QSaherMemory object. I don't try still it, but... :)

    Regards,
    Norbert



  • Unfortunately QMutex won't work this way. However, check boost.interprocess, there is shared-memory stored interprocess_mutex, and contains try_lock as well ;)
    Could you share your solution for your problem, please? It could be helpful for the others.



  • [quote author="moravas" date="1365711105"]I have an interest idea: a QMutex object on a QSaherMemory object. I don't try still it, but... :)[/quote]

    How do you do that ?

    If you create a new QMutex via new operator, it will be created on the Heap space by the C++ runtime and you have no way to specify that it should be created in the "shared" memory area. You could store the pointer to the new QMutex in the "shared" memory area, sure. But that wouldn't work very well. Any process, except for the one process that created the QMutex object, would probably just crash when trying to dereference this pointer.

    The alternative, creating the QMutex as an "local" (auto) object, would create it on the stack memory of the process/thread who creates the object. So, that certainly doesn't work either.



  • Hi,

    Bogdan:
    sorry, but I don't understand your demand:
    "Could you share your solution for your problem, please? It could be helpful for the others."
    Would you like to I make an wikipedia page, or simple post a solution in this thread?

    MuldeR:
    In C++ you can determine the location of an object via "new" operator. This solution is very dangerous, but in some cases is it able to work. It is the placement operator of new. If you are use some Linux distribution, you can check it in "/usr/include/c++/4.7/new" file (it is my PATH, it may be different for you.)
    The advantage for placement new is that you can specifies the memory are which will contain your object: placement new operator make a constructor calling.
    The disadvantages are for placement new that I don't known the behaviour of the object if it use dynamical allocated memory.
    I don't known the behaviour of the virtual functions and other run time part of C++ in this aspect.
    For more details can you check the following links:
    http://www.parashift.com/c++-faq/placement-new.html
    http://stackoverflow.com/questions/222557/what-uses-are-there-for-placement-new
    http://en.wikipedia.org/wiki/Placement_syntax

    Regards,
    Norbert



  • Well, just share a main idea of your solution if you can. I don't want you write wiki, or share sources :) You needed to synchronize QSharedMemory, but you didn't want to use lock/unlock, and you didn't use shared file, and QSystemSemaphore didn't work for you. So I'm just curious: what have you used?

    And about placement new and QMutex: it's general idea behind interprocess_mutex as it's placed in shared memory (or memory mapped file), so you could be right, but I'm not sure if QMutex fits some (unknown for me) requirements for such solution.



  • Hi,

    sorry for my late, but I had to work on my projects :)
    So something about my solution:
    The base concept was the following:

    • I would like establish an unidirectional communication between two process. A write a messages into the FIFO and B read those.
      I tried to decompose the problem: same FIFO, same operations, same connections...
      They are implemented in an dynamical linked library(I don't like .dll: it is so Microsoft...)
      This inherited from an common base class which contains one pure virtual method:
      @
      protected: virtual void makeFIFOOnSharedMemory() = 0;
      @

    and it looks like on the sender side:
    @
    private: virtual void makeFIFOOnSharedMemory() {
    _fifo = dynamic_cast<messageFIFO*>(new (_sharedMemory->data()) messageFIFO());
    if(_fifo == nullptr) {throw new SharedMemoryError();}
    }
    @

    and the receiver site:
    @
    private : virtual void makeFIFOOnSharedMemory() {
    _fifo = reinterpret_cast<messageFIFO*>(_sharedMemory->data());
    if(_fifo == nullptr) {throw new SharedMemoryError();}
    }
    @

    considering that to the correct operation I have to check the an existent instance of receiver process. This is the constructor of sender site
    @
    Logging::Logging(): _level(logLevel::all) {

    QProcess checkExistingInstance;
    checkExistingInstance.start("ps", QStringList() << "alx");
    checkExistingInstance.waitForFinished();
    
    if(!checkExistingInstance.readAllStandardOutput().contains("backgroundWorkerLogging")) {
        _backgroundProcess.reset(new QProcess(this));
        _backgroundProcess->start("../backgroundWorkerLogging/backgroundWorkerLogging");
        _backgroundProcess->waitForStarted(-1);
    }
    
    makeFIFOOnSharedMemory();
    

    }
    @

    It is not a precise solution for IPC but it works for my requirement.

    Regards,
    Norbert



  • Thanks Norbert!

    Could I ask you how you synchronize access to messageFIFO object? You wrote that neither lock/unlock nor QSystemSemaphore didn't work for you. I understand that shared memory, and messageFIFO inside, need to be synchronized between operations in separated processes, am I right?


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.