#include "shared_mem_buffer.h" #include #include #include #include #include #include #include #include #ifdef QT_POSIX_IPC // The POSIX backend can be explicitly selected using the -feature-ipc_posix // option to the Qt configure script. If it is enabled, the QT_POSIX_IPC // macro will be defined. -> we use SystemV shared memory #error "QT_POSIX_IPC defined" #else #ifdef linux #include #include #include // 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"; #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; } } } 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; } // std::atomic_bool SharedMemBuffer::__sharedMemLocked{false}; /* //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(); #else static const QString fkey = "0123456?000=9"; #endif shdMemFirstUse=false; shMem.setKey(fkey); if (!shMem.isAttached()) { if (shMem.create(size)) { // sm was created successful, did not exist before shdMemFirstUse=true; return &shMem; } else { // create was false because mem already existed if (shMem.error() == QSharedMemory::AlreadyExists) { if (shMem.attach()) { return &shMem; } } } qCritical() << shMem.nativeKey() << shMem.key() << shMem.data() << shMem.error() << shMem.errorString(); return nullptr; } } return &shMem; } bool shdMem_firstUse(void) { return shdMemFirstUse; } */