forked from GerhardHoffmann/DCLibraries
		
	Improved creating/attaching shared memory: there is a possibility of a stale shared memory
under /tmp.
This commit is contained in:
		@@ -1,7 +1,13 @@
 | 
			
		||||
#include "shared_mem_buffer.h"
 | 
			
		||||
 | 
			
		||||
#include <QDebug>
 | 
			
		||||
#include <QFile>
 | 
			
		||||
#include <QString>
 | 
			
		||||
#include <QTextStream>
 | 
			
		||||
#include <QDateTime>
 | 
			
		||||
#include <QCoreApplication>
 | 
			
		||||
#include <atomic>
 | 
			
		||||
#include <algorithm>
 | 
			
		||||
 | 
			
		||||
#ifdef QT_POSIX_IPC
 | 
			
		||||
    // The POSIX backend can be explicitly selected using the -feature-ipc_posix
 | 
			
		||||
@@ -9,33 +15,124 @@
 | 
			
		||||
    // macro will be defined. -> we use SystemV shared memory
 | 
			
		||||
#error "QT_POSIX_IPC defined"
 | 
			
		||||
#else
 | 
			
		||||
#ifdef __linux__
 | 
			
		||||
#ifdef linux
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <sys/ipc.h>    // ftok
 | 
			
		||||
#endif
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
//static bool shdMemFirstUse;
 | 
			
		||||
 | 
			
		||||
static QString read1stLineOfFile(QString fileName) { // read for instance /etc/os-release
 | 
			
		||||
    QFile f(fileName);
 | 
			
		||||
    if (f.exists()) {
 | 
			
		||||
        if (f.open(QIODevice::ReadOnly | QIODevice::Text)) {
 | 
			
		||||
            QTextStream in(&f);
 | 
			
		||||
            in.setCodec("UTF-8");
 | 
			
		||||
            while(!in.atEnd()) {
 | 
			
		||||
                return in.readLine();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return "N/A";
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
//QSharedMemory *SharedMemBuffer::getShm(std::size_t size) {
 | 
			
		||||
QSharedMemory *SharedMem::getShm(std::size_t size) {
 | 
			
		||||
    static QSharedMemory shMem;
 | 
			
		||||
    if (size > 0) {
 | 
			
		||||
#ifdef __linux__
 | 
			
		||||
        //static const long nativeKey = ftok("/etc/os-release", 'H');
 | 
			
		||||
        //static const QString fkey = std::to_string(nativeKey).c_str();
 | 
			
		||||
        static const QString fkey = "0123456?000=7";
 | 
			
		||||
#ifdef linux
 | 
			
		||||
        static const long nativeKey = ftok("/etc/os-release", 'H');
 | 
			
		||||
        static const QString fkey = std::to_string(nativeKey).c_str();
 | 
			
		||||
        //static const QString fkey = "0123456?000=7";
 | 
			
		||||
#else
 | 
			
		||||
        static const QString fkey = "0123456?000=9";
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
        qCritical() << __func__ << ":" << __LINE__ << ": size" << size;
 | 
			
		||||
 | 
			
		||||
        shMem.setKey(fkey);
 | 
			
		||||
        if (!shMem.isAttached()) {
 | 
			
		||||
            if (shMem.create(size)) {
 | 
			
		||||
                qCritical() << __func__ << ":" << __LINE__ << ": created shared memory";
 | 
			
		||||
 | 
			
		||||
#ifdef linux
 | 
			
		||||
                if ((size != (std::size_t)shMem.size()) || (sizeof(SharedMem) != shMem.size())) {
 | 
			
		||||
                    qCritical() << __func__ << ":" << __LINE__
 | 
			
		||||
                                << "size=" << size
 | 
			
		||||
                                << "shMem.size=" << shMem.size()
 | 
			
		||||
                                << "sizeof(SharedMem)=" << sizeof(SharedMem)
 | 
			
		||||
                                << "ABOUT TO REBOOT SYSTEM...";
 | 
			
		||||
                    if (system("reboot")) {
 | 
			
		||||
                        // reboot system -> shared memory re-created
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                struct SharedMem *sh = (SharedMem *)(shMem.data());
 | 
			
		||||
 | 
			
		||||
                memset(sh->indat_HWversion, 0x00, sizeof(sh->indat_HWversion));
 | 
			
		||||
                memset(sh->indat_SWversion, 0x00, sizeof(sh->indat_SWversion));
 | 
			
		||||
 | 
			
		||||
                memset(sh->os_release, 0x00, sizeof(sh->os_release));
 | 
			
		||||
                memset(sh->date_of_creation, 0x00, sizeof(sh->date_of_creation));
 | 
			
		||||
                memset(sh->creator, 0x00, sizeof(sh->creator));
 | 
			
		||||
 | 
			
		||||
                QString const &os_release = read1stLineOfFile("/etc/os-release");
 | 
			
		||||
                strncpy(sh->os_release, os_release.toStdString().c_str(),
 | 
			
		||||
                        std::min((int)os_release.size(), (int)sizeof(sh->os_release)-1));
 | 
			
		||||
 | 
			
		||||
                QString const ¤tDateTime = QDateTime::currentDateTime().toString(Qt::ISODate);
 | 
			
		||||
                char const *current = currentDateTime.toUtf8().constData();
 | 
			
		||||
                strncpy(sh->date_of_creation, current,
 | 
			
		||||
                        std::min((int)strlen(current), (int)sizeof(sh->date_of_creation)-1));
 | 
			
		||||
 | 
			
		||||
                QString const &appPid = QString("%1 (%2)").arg(QCoreApplication::applicationName())
 | 
			
		||||
                                                          .arg(QCoreApplication::applicationPid());
 | 
			
		||||
 | 
			
		||||
                strncpy(sh->creator, appPid.toStdString().c_str(),
 | 
			
		||||
                        std::min((int)strlen(appPid.toStdString().c_str()),
 | 
			
		||||
                                 (int)sizeof(sh->creator)-1));
 | 
			
		||||
 | 
			
		||||
                qCritical() << "os-release:" << sh->os_release;
 | 
			
		||||
                qCritical() << "   creator:" << sh->creator;
 | 
			
		||||
                qCritical() << "      date:" << sh->date_of_creation;
 | 
			
		||||
 | 
			
		||||
#else
 | 
			
		||||
                Q_ASSERT_X(size != shMem.size(), "compare sizes", "sizes different");
 | 
			
		||||
                Q_ASSERT_X(sizeof(SharedMem) != shMem.size(), "compare sizes", "sizes different");
 | 
			
		||||
#endif
 | 
			
		||||
                return &shMem;
 | 
			
		||||
            } else {
 | 
			
		||||
                if (shMem.error() == QSharedMemory::AlreadyExists) {
 | 
			
		||||
                    if (shMem.attach()) {
 | 
			
		||||
#ifdef linux
 | 
			
		||||
                        if ((size != (std::size_t)shMem.size()) || (sizeof(SharedMem) != shMem.size())) {
 | 
			
		||||
                            qCritical() << __func__ << ":" << __LINE__
 | 
			
		||||
                                        << "size=" << size
 | 
			
		||||
                                        << "shMem.size=" << shMem.size()
 | 
			
		||||
                                        << "sizeof(SharedMem)=" << sizeof(SharedMem)
 | 
			
		||||
                                        << "ABOUT TO REBOOT SYSTEM...";
 | 
			
		||||
                            if (system("reboot")) {
 | 
			
		||||
                                // reboot system -> shared memory re-created
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
#else
 | 
			
		||||
                        Q_ASSERT_X(size != shMem.size(), "compare sizes", "sizes different");
 | 
			
		||||
                        Q_ASSERT_X(sizeof(SharedMem) != shMem.size(), "compare sizes", "sizes different");
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
                        QString const &appPid = QString("%1 (%2)").arg(QCoreApplication::applicationName())
 | 
			
		||||
                                                                  .arg(QCoreApplication::applicationPid());
 | 
			
		||||
 | 
			
		||||
                        qCritical() << __func__ << ":" << __LINE__ << appPid << "attached shared memory";
 | 
			
		||||
 | 
			
		||||
                        struct SharedMem const *sh = (SharedMem const *)(shMem.data());
 | 
			
		||||
                        qCritical() << "os-release:" << sh->os_release;
 | 
			
		||||
                        qCritical() << "   creator:" << sh->creator;
 | 
			
		||||
                        qCritical() << "      date:" << sh->date_of_creation;
 | 
			
		||||
 | 
			
		||||
                        return &shMem;
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
@@ -43,6 +140,13 @@ QSharedMemory *SharedMem::getShm(std::size_t size) {
 | 
			
		||||
            qCritical() << shMem.nativeKey() << shMem.key() << shMem.data()
 | 
			
		||||
                        << shMem.error() << shMem.errorString();
 | 
			
		||||
            return nullptr;
 | 
			
		||||
        } else {
 | 
			
		||||
            qCritical() << __func__ << ":" << __LINE__ << "shared memory already attached";
 | 
			
		||||
 | 
			
		||||
            struct SharedMem const *sh = (SharedMem const *)(shMem.data());
 | 
			
		||||
            qCritical() << "os-release:" << sh->os_release;
 | 
			
		||||
            qCritical() << "   creator:" << sh->creator;
 | 
			
		||||
            qCritical() << "      date:" << sh->date_of_creation;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return &shMem;
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user