Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. How to share data between processes using QSharedMemory?
Forum Updated to NodeBB v4.3 + New Features

How to share data between processes using QSharedMemory?

Scheduled Pinned Locked Moved Unsolved General and Desktop
15 Posts 4 Posters 1.6k Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • R Offline
    R Offline
    Roberrt
    wrote on last edited by
    #1

    In my attempt bellow, when i read the struct Data on process 2
    Data *dataInMemory = static_cast<Data*>(sharedMemory.data());
    looks like its corrupted: 34f8c473-41f2-4190-876c-2fc60a8f13f3-image.png

    and the application crash in the next line.

    What i'm doing wrong?

    process 1

    struct Data {
        QMap<int, QString> map;
    };
    
    Process1::Process1(QWidget* parent) : QMainWindow(parent), ui(new Ui::Process1Class())
    {
        ui->setupUi(this);
    
        // Create an instance of QSharedMemory and attach
        // it to a unique key.
        sharedMemory.setKey("Key");
    
        Data data;
        data.map[1] = "Hello";
        data.map[2] = "World";
    
        if (!sharedMemory.create(sizeof(Data))) {
            if (!sharedMemory.attach()) {
                qWarning() << "Unable to attach to shared memory: " << sharedMemory.errorString();;
                return;
            }
        } else {
            // Shared memory doesn't exist, create it and initialize the shared data.
            sharedMemory.lock();
            Data *data = static_cast<Data*>(sharedMemory.data());
            sharedMemory.unlock();
        }
    
        sharedMemory.lock();
        Data *dataInMemory = static_cast<Data*>(sharedMemory.data());
        *dataInMemory = data;
        sharedMemory.unlock();
    }
    

    process 2

    struct Data {
        QMap<int, QString> map;
    };
    
    Process2::Process2(QWidget *parent) : QMainWindow(parent), ui(new Ui::Process2Class())
    {
        ui->setupUi(this);
    
        // Create an instance of QSharedMemory and attach it 
        // to the same key as process 1.
        QSharedMemory sharedMemory("Key");
    
        if (!sharedMemory.attach()) {
            qWarning() << "Unable to attach to shared memory: " << sharedMemory.errorString();;
            return;
        }
    
        sharedMemory.lock();
        Data *dataInMemory = static_cast<Data*>(sharedMemory.data());
        QMap<int, QString> map = dataInMemory->map;
        sharedMemory.unlock();
    }
    
    Christian EhrlicherC 1 Reply Last reply
    0
    • R Roberrt

      In my attempt bellow, when i read the struct Data on process 2
      Data *dataInMemory = static_cast<Data*>(sharedMemory.data());
      looks like its corrupted: 34f8c473-41f2-4190-876c-2fc60a8f13f3-image.png

      and the application crash in the next line.

      What i'm doing wrong?

      process 1

      struct Data {
          QMap<int, QString> map;
      };
      
      Process1::Process1(QWidget* parent) : QMainWindow(parent), ui(new Ui::Process1Class())
      {
          ui->setupUi(this);
      
          // Create an instance of QSharedMemory and attach
          // it to a unique key.
          sharedMemory.setKey("Key");
      
          Data data;
          data.map[1] = "Hello";
          data.map[2] = "World";
      
          if (!sharedMemory.create(sizeof(Data))) {
              if (!sharedMemory.attach()) {
                  qWarning() << "Unable to attach to shared memory: " << sharedMemory.errorString();;
                  return;
              }
          } else {
              // Shared memory doesn't exist, create it and initialize the shared data.
              sharedMemory.lock();
              Data *data = static_cast<Data*>(sharedMemory.data());
              sharedMemory.unlock();
          }
      
          sharedMemory.lock();
          Data *dataInMemory = static_cast<Data*>(sharedMemory.data());
          *dataInMemory = data;
          sharedMemory.unlock();
      }
      

      process 2

      struct Data {
          QMap<int, QString> map;
      };
      
      Process2::Process2(QWidget *parent) : QMainWindow(parent), ui(new Ui::Process2Class())
      {
          ui->setupUi(this);
      
          // Create an instance of QSharedMemory and attach it 
          // to the same key as process 1.
          QSharedMemory sharedMemory("Key");
      
          if (!sharedMemory.attach()) {
              qWarning() << "Unable to attach to shared memory: " << sharedMemory.errorString();;
              return;
          }
      
          sharedMemory.lock();
          Data *dataInMemory = static_cast<Data*>(sharedMemory.data());
          QMap<int, QString> map = dataInMemory->map;
          sharedMemory.unlock();
      }
      
      Christian EhrlicherC Online
      Christian EhrlicherC Online
      Christian Ehrlicher
      Lifetime Qt Champion
      wrote on last edited by
      #2

      You can not share objects snce most of them have pointers to other memory in their private implementations - only plain data, or serialized objects

      Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
      Visit the Qt Academy at https://academy.qt.io/catalog

      R 1 Reply Last reply
      2
      • Christian EhrlicherC Christian Ehrlicher

        You can not share objects snce most of them have pointers to other memory in their private implementations - only plain data, or serialized objects

        R Offline
        R Offline
        Roberrt
        wrote on last edited by
        #3

        @Christian-Ehrlicher how to serialize the object? qt has implementation for this task?

        Christian EhrlicherC JonBJ 2 Replies Last reply
        0
        • R Roberrt

          @Christian-Ehrlicher how to serialize the object? qt has implementation for this task?

          Christian EhrlicherC Online
          Christian EhrlicherC Online
          Christian Ehrlicher
          Lifetime Qt Champion
          wrote on last edited by
          #4

          @Roberrt said in How to share data between processes using QSharedMemory?:

          qt has implementation for this task?

          You can use QDataStream for it.

          Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
          Visit the Qt Academy at https://academy.qt.io/catalog

          1 Reply Last reply
          1
          • R Roberrt

            @Christian-Ehrlicher how to serialize the object? qt has implementation for this task?

            JonBJ Offline
            JonBJ Offline
            JonB
            wrote on last edited by
            #5

            @Roberrt
            And Serializing Qt Data Types lists which Qt classes come with support. Note that this does not include any kind of QObject!

            1 Reply Last reply
            1
            • R Offline
              R Offline
              Roberrt
              wrote on last edited by Roberrt
              #6

              I got it working now, something that i should change or take note?
              process1

              struct Data {
                  QMap<int, QString> map;
              };
              
              filemap1::filemap1(QWidget* parent)
                  : QMainWindow(parent)
                  , ui(new Ui::filemap1Class())
              {
                  ui->setupUi(this);
              
                  // Create an instance of QSharedMemory and attach it to a unique key
                  sharedMemory.setKey("MyKey");
              
                  Data data;
                  data.map[1] = "Hello";
                  data.map[2] = "World";
              
                  QByteArray serializedData;
                  QDataStream stream(&serializedData, QIODevice::WriteOnly);
                  stream << data.map;
              
                  if (!sharedMemory.create(serializedData.size())) 
                  {
                      if (!sharedMemory.attach()) {
                          qWarning() << "Unable to attach to shared memory: " << sharedMemory.errorString();;
                          return;
                      }
                  }
              
                  sharedMemory.lock();
                  char* sharedMemoryData = static_cast<char*>(sharedMemory.data());
                  std::memcpy(sharedMemoryData, serializedData.constData(), serializedData.size());
                  sharedMemory.unlock();
              }
              

              process2

              struct Data {
                  QMap<int, QString> map;
              };
              
              filemap2::filemap2(QWidget *parent) : QMainWindow(parent) , ui(new Ui::filemap2Class())
              {
                  ui->setupUi(this);
              
                  // Create an instance of QSharedMemory and attach it 
                  // to the same key as process 1
                  QSharedMemory sharedMemory("MyKey");
                  if (!sharedMemory.attach()) {
                      qWarning() << "Unable to attach to shared memory: " << sharedMemory.errorString();;
                      return;
                  }
              
                  sharedMemory.lock();
                  // Read the serialized data from shared memory
                  char* sharedMemoryData = static_cast<char*>(sharedMemory.data());
                  QByteArray serializedData(sharedMemoryData, sharedMemory.size());
              
                  // Deserialize the object
                  QDataStream stream(&serializedData, QIODevice::ReadOnly);
                  Data data;
                  stream >> data.map;
              
                  sharedMemory.unlock();
              }
              

              How do i avoid the process getting stuck when trying to attach to a sharedMemory which is locked for too much time?

              For example, if process2 lock the sharedMemory and crash, when process1 try to read it, it will stuck, as it wait forever to the memory be unlocked.

              JonBJ 1 Reply Last reply
              0
              • R Roberrt

                I got it working now, something that i should change or take note?
                process1

                struct Data {
                    QMap<int, QString> map;
                };
                
                filemap1::filemap1(QWidget* parent)
                    : QMainWindow(parent)
                    , ui(new Ui::filemap1Class())
                {
                    ui->setupUi(this);
                
                    // Create an instance of QSharedMemory and attach it to a unique key
                    sharedMemory.setKey("MyKey");
                
                    Data data;
                    data.map[1] = "Hello";
                    data.map[2] = "World";
                
                    QByteArray serializedData;
                    QDataStream stream(&serializedData, QIODevice::WriteOnly);
                    stream << data.map;
                
                    if (!sharedMemory.create(serializedData.size())) 
                    {
                        if (!sharedMemory.attach()) {
                            qWarning() << "Unable to attach to shared memory: " << sharedMemory.errorString();;
                            return;
                        }
                    }
                
                    sharedMemory.lock();
                    char* sharedMemoryData = static_cast<char*>(sharedMemory.data());
                    std::memcpy(sharedMemoryData, serializedData.constData(), serializedData.size());
                    sharedMemory.unlock();
                }
                

                process2

                struct Data {
                    QMap<int, QString> map;
                };
                
                filemap2::filemap2(QWidget *parent) : QMainWindow(parent) , ui(new Ui::filemap2Class())
                {
                    ui->setupUi(this);
                
                    // Create an instance of QSharedMemory and attach it 
                    // to the same key as process 1
                    QSharedMemory sharedMemory("MyKey");
                    if (!sharedMemory.attach()) {
                        qWarning() << "Unable to attach to shared memory: " << sharedMemory.errorString();;
                        return;
                    }
                
                    sharedMemory.lock();
                    // Read the serialized data from shared memory
                    char* sharedMemoryData = static_cast<char*>(sharedMemory.data());
                    QByteArray serializedData(sharedMemoryData, sharedMemory.size());
                
                    // Deserialize the object
                    QDataStream stream(&serializedData, QIODevice::ReadOnly);
                    Data data;
                    stream >> data.map;
                
                    sharedMemory.unlock();
                }
                

                How do i avoid the process getting stuck when trying to attach to a sharedMemory which is locked for too much time?

                For example, if process2 lock the sharedMemory and crash, when process1 try to read it, it will stuck, as it wait forever to the memory be unlocked.

                JonBJ Offline
                JonBJ Offline
                JonB
                wrote on last edited by JonB
                #7

                @Roberrt
                I think the attach() is OK, you mean when the second process tries a lock().
                I think the answer is that Qt does not provide any kind of tryLock(), see https://bugreports.qt.io/browse/QTBUG-4073 and https://bugreports.qt.io/browse/QTBUG-2443.
                I don't know what happens of one side actually "crashes", OS-dependent behaviour as to whether it gets released.
                There may be other ways to share data with IPC which don't risk this QSharedMemory behaviour if that is important to you.

                R 1 Reply Last reply
                0
                • JonBJ JonB

                  @Roberrt
                  I think the attach() is OK, you mean when the second process tries a lock().
                  I think the answer is that Qt does not provide any kind of tryLock(), see https://bugreports.qt.io/browse/QTBUG-4073 and https://bugreports.qt.io/browse/QTBUG-2443.
                  I don't know what happens of one side actually "crashes", OS-dependent behaviour as to whether it gets released.
                  There may be other ways to share data with IPC which don't risk this QSharedMemory behaviour if that is important to you.

                  R Offline
                  R Offline
                  Roberrt
                  wrote on last edited by
                  #8

                  @JonB How to keep the sharedMemory even after process1 exit?

                  JonBJ 1 Reply Last reply
                  0
                  • R Roberrt

                    @JonB How to keep the sharedMemory even after process1 exit?

                    JonBJ Offline
                    JonBJ Offline
                    JonB
                    wrote on last edited by
                    #9

                    @Roberrt
                    Have you read the platform description in https://doc.qt.io/qt-6/qsharedmemory.html#details ?

                    It also says

                    QSharedMemory automatically destroys the shared memory segment when the last instance of QSharedMemory is detached from the segment, and no references to the segment remain.

                    I think if process1 exits but process 2 has attached it persists. Until all processes have released it.

                    R 1 Reply Last reply
                    1
                    • JonBJ JonB

                      @Roberrt
                      Have you read the platform description in https://doc.qt.io/qt-6/qsharedmemory.html#details ?

                      It also says

                      QSharedMemory automatically destroys the shared memory segment when the last instance of QSharedMemory is detached from the segment, and no references to the segment remain.

                      I think if process1 exits but process 2 has attached it persists. Until all processes have released it.

                      R Offline
                      R Offline
                      Roberrt
                      wrote on last edited by
                      #10

                      @JonB I see, whats the best way to inform process2 that new data has been written to the QSharedMemory?

                      JonBJ 1 Reply Last reply
                      0
                      • R Roberrt

                        @JonB I see, whats the best way to inform process2 that new data has been written to the QSharedMemory?

                        JonBJ Offline
                        JonBJ Offline
                        JonB
                        wrote on last edited by
                        #11

                        @Roberrt
                        You might have to have a semaphore for that. There isn't a "notification".
                        Before you go any further you should read

                        • https://forum.qt.io/topic/120197/qsharedmemory-update-signal
                        • https://stackoverflow.com/questions/37121384/observe-changes-in-qsharedmemory

                        and consider your alternatives, and what you are using the shared memory for.

                        1 Reply Last reply
                        0
                        • Kent-DorfmanK Offline
                          Kent-DorfmanK Offline
                          Kent-Dorfman
                          wrote on last edited by
                          #12

                          Another huge mistake people make when using shared memory is they think in terms of peer-to-peer, which is bad juju. You really have to manage shared memory as a master/slave relationship. ie, it is set-up/initialized by a controller and then some number of other processes can use it...and there is no implicit "notify of changes" mechanism. you have to poll for changes or implement some sort of cross-process signalling mechanism in addition to correct use of semaphores/mutexes.

                          1 Reply Last reply
                          1
                          • R Offline
                            R Offline
                            Roberrt
                            wrote on last edited by
                            #13

                            Do i still need to call .lock into the QSharedMemory when i'm just reading it without modifying the data?

                            JonBJ Kent-DorfmanK 2 Replies Last reply
                            0
                            • R Roberrt

                              Do i still need to call .lock into the QSharedMemory when i'm just reading it without modifying the data?

                              JonBJ Offline
                              JonBJ Offline
                              JonB
                              wrote on last edited by JonB
                              #14

                              @Roberrt
                              void *QSharedMemory::data()

                              Remember to lock the shared memory with lock() before reading from or writing to the shared memory

                              If you don't lock() for read and someone else has lock()ed and writes, I simply don't know/maybe not defined what you see in the read.

                              1 Reply Last reply
                              0
                              • R Roberrt

                                Do i still need to call .lock into the QSharedMemory when i'm just reading it without modifying the data?

                                Kent-DorfmanK Offline
                                Kent-DorfmanK Offline
                                Kent-Dorfman
                                wrote on last edited by Kent-Dorfman
                                #15

                                @Roberrt

                                Read characteristics are undefined if you don't guarantee exclusive access, or at least use data types that are guaranteed to be atomic. Generally the read of a native word sized int is atomic across architectures because the CPU microcode likes to deal with a whole word at a time, and preemption wont occur in the middle of a machine code instruction.

                                But it is safer to lock for reads as well.

                                1 Reply Last reply
                                1

                                • Login

                                • Login or register to search.
                                • First post
                                  Last post
                                0
                                • Categories
                                • Recent
                                • Tags
                                • Popular
                                • Users
                                • Groups
                                • Search
                                • Get Qt Extensions
                                • Unsolved