Fix some IPC issues

This commit is contained in:
Nova 2025-02-24 12:57:22 +03:30
parent 4034b19f85
commit 6751493c0f
4 changed files with 24 additions and 136 deletions

98
3rdparty/RunGuard.hpp vendored
View File

@ -1,98 +0,0 @@
#ifndef RUNGUARD_H
#define RUNGUARD_H
#include <QObject>
#include <QSharedMemory>
#include <QSystemSemaphore>
#include <QCryptographicHash>
class RunGuard {
public:
RunGuard(const QString &key);
~RunGuard();
bool isAnotherRunning(quint64 *data_out);
bool tryToRun(quint64 *data_in);
void release();
private:
const QString key;
const QString memLockKey;
const QString sharedmemKey;
QSharedMemory sharedMem;
QSystemSemaphore memLock;
Q_DISABLE_COPY(RunGuard)
};
namespace {
QString generateKeyHash(const QString &key, const QString &salt) {
QByteArray data;
data.append(key.toUtf8());
data.append(salt.toUtf8());
data = QCryptographicHash::hash(data, QCryptographicHash::Sha1).toHex();
return data;
}
} // namespace
RunGuard::RunGuard(const QString &key)
: key(key), memLockKey(generateKeyHash(key, "_memLockKey")), sharedmemKey(generateKeyHash(key, "_sharedmemKey")), sharedMem(sharedmemKey), memLock(memLockKey, 1) {
memLock.acquire();
{
QSharedMemory fix(sharedmemKey); // Fix for *nix: http://habrahabr.ru/post/173281/
fix.attach();
}
memLock.release();
}
RunGuard::~RunGuard() {
release();
}
bool RunGuard::isAnotherRunning(quint64 *data_out) {
if (sharedMem.isAttached())
return false;
memLock.acquire();
const bool isRunning = sharedMem.attach();
if (isRunning) {
if (data_out != nullptr) {
memcpy(data_out, sharedMem.data(), sizeof(quint64));
}
sharedMem.detach();
}
memLock.release();
return isRunning;
}
bool RunGuard::tryToRun(quint64 *data_in) {
memLock.acquire();
const bool result = sharedMem.create(sizeof(quint64));
if (result) memcpy(sharedMem.data(), data_in, sizeof(quint64));
memLock.release();
if (!result) {
release();
return false;
}
return true;
}
void RunGuard::release() {
memLock.acquire();
if (sharedMem.isAttached())
sharedMem.detach();
memLock.release();
}
#endif // RUNGUARD_H

View File

@ -11,10 +11,6 @@
inline QString software_name = "NekoRay";
inline QString software_core_name = "Xray";
// Main Functions
inline std::function<void()> MF_release_runguard;
// MainWindow functions
class QWidget;
inline QWidget *mainwindow;

View File

@ -10,7 +10,6 @@
#include <QThread>
#include <3rdparty/WinCommander.hpp>
#include "3rdparty/RunGuard.hpp"
#include "include/global/NekoGui.hpp"
#include "include/ui/mainwindow_interface.h"
@ -117,30 +116,6 @@ int main(int argc, char* argv[]) {
DS_cores = new QThread;
DS_cores->start();
// RunGuard
RunGuard guard("nekoray" + wd.absolutePath());
quint64 guard_data_in = GetRandomUint64();
quint64 guard_data_out = 0;
if (!NekoGui::dataStore->flag_many && !guard.tryToRun(&guard_data_in)) {
// Some Good System
if (guard.isAnotherRunning(&guard_data_out)) {
// Wake up a running instance
QLocalSocket socket;
socket.connectToServer(LOCAL_SERVER_PREFIX + Int2String(guard_data_out));
qDebug() << socket.fullServerName();
if (!socket.waitForConnected(500)) {
qDebug() << "Failed to wake a running instance.";
return 0;
}
qDebug() << "connected to local server, try to raise another program";
return 0;
}
// Some Bad System
QMessageBox::warning(nullptr, "NekoRay", "RunGuard disallow to run, use -many to force start.");
return 0;
}
MF_release_runguard = [&] { guard.release(); };
// icons
QIcon::setFallbackSearchPaths(QStringList{
":/nekoray",
@ -241,15 +216,30 @@ int main(int argc, char* argv[]) {
signal(SIGTERM, signal_handler);
signal(SIGINT, signal_handler);
// Check if another instance is running
QLocalSocket socket;
socket.connectToServer(LOCAL_SERVER_PREFIX + wd.absolutePath());
if (socket.waitForConnected(500))
{
qDebug() << "Another instance is running, let's wake it up and quit";
socket.write("Wake up!");
socket.disconnectFromServer();
return 0;
}
// QLocalServer
QLocalServer server;
auto server_name = LOCAL_SERVER_PREFIX + Int2String(guard_data_in);
QLocalServer server(qApp);
auto server_name = LOCAL_SERVER_PREFIX + wd.absolutePath();
QLocalServer::removeServer(server_name);
server.listen(server_name);
QObject::connect(&server, &QLocalServer::newConnection, &a, [&] {
auto socket = server.nextPendingConnection();
qDebug() << "nextPendingConnection:" << server_name << socket;
socket->deleteLater();
server.setSocketOptions(QLocalServer::WorldAccessOption);
if (!server.listen(server_name)) {
qWarning() << "Failed to start QLocalServer! Error:" << server.errorString();
return 1;
}
QObject::connect(&server, &QLocalServer::newConnection, qApp, [&] {
auto s = server.nextPendingConnection();
qDebug() << "Another instance tried to wake us up on " << server_name << s;
s->deleteLater();
// raise main window
MW_dialog_message("", "Raise");
});

View File

@ -606,7 +606,8 @@ void MainWindow::dialog_message_impl(const QString &sender, const QString &info)
if (info == "RestartProgram") {
this->exit_reason = 2;
on_menu_exit_triggered();
} else if (info == "Raise") {
}
if (info == "Raise") {
ActivateWindow(this);
}
if (info == "NeedAdmin") {
@ -750,7 +751,6 @@ void MainWindow::on_menu_exit_triggered() {
return;
}
//
MF_release_runguard();
if (exit_reason == 1) {
QDir::setCurrent(QApplication::applicationDirPath());
QProcess::startDetached("./updater", QStringList{});