mirror of
https://github.com/Mahdi-zarei/nekoray.git
synced 2025-12-19 13:42:51 +08:00
Fix some IPC issues
This commit is contained in:
parent
4034b19f85
commit
6751493c0f
98
3rdparty/RunGuard.hpp
vendored
98
3rdparty/RunGuard.hpp
vendored
@ -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
|
||||
@ -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;
|
||||
|
||||
54
src/main.cpp
54
src/main.cpp
@ -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");
|
||||
});
|
||||
|
||||
@ -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{});
|
||||
|
||||
Loading…
Reference in New Issue
Block a user