mirror of
https://github.com/qTox/qTox.git
synced 2024-03-22 14:00:36 +08:00
Profile locking
This commit is contained in:
parent
13d98da1bc
commit
bbf75aefb9
2
qtox.pro
2
qtox.pro
|
@ -430,6 +430,7 @@ SOURCES += \
|
|||
src/core/coreencryption.cpp \
|
||||
src/core/corefile.cpp \
|
||||
src/core/corestructs.cpp \
|
||||
src/profilelocker.cpp
|
||||
|
||||
HEADERS += \
|
||||
src/audio.h \
|
||||
|
@ -454,3 +455,4 @@ HEADERS += \
|
|||
src/widget/gui.h \
|
||||
src/toxme.h \
|
||||
src/misc/qrwidget.h \
|
||||
src/profilelocker.h
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include "src/widget/gui.h"
|
||||
#include "src/historykeeper.h"
|
||||
#include "src/audio.h"
|
||||
#include "src/profilelocker.h"
|
||||
#include "corefile.h"
|
||||
|
||||
#include <tox/tox.h>
|
||||
|
@ -884,6 +885,17 @@ QByteArray Core::loadToxSave(QString path)
|
|||
QByteArray data;
|
||||
loadPath = ""; // if not empty upon return, then user forgot a password and is switching
|
||||
|
||||
// If we can't get a lock, then another instance is already using that profile
|
||||
while (!ProfileLocker::lock(QFileInfo(path).baseName()))
|
||||
{
|
||||
qWarning() << "Profile "<<QFileInfo(path).baseName()<<" is already in use, pick another";
|
||||
GUI::showWarning(tr("Profile already in use"),
|
||||
tr("Your profile is already used by another qTox\n"
|
||||
"Please select another profile"));
|
||||
path = Settings::getInstance().askProfiles();
|
||||
qWarning() << "New profile is "<<QFileInfo(path).baseName();
|
||||
}
|
||||
|
||||
QFile configurationFile(path);
|
||||
qDebug() << "Core::loadConfiguration: reading from " << path;
|
||||
|
||||
|
@ -913,9 +925,9 @@ QByteArray Core::loadToxSave(QString path)
|
|||
|
||||
if (!profile.isEmpty())
|
||||
{
|
||||
loadPath = QDir(Settings::getSettingsDirPath()).filePath(profile + TOX_EXT);
|
||||
Settings::getInstance().switchProfile(profile);
|
||||
HistoryKeeper::resetInstance();
|
||||
return loadToxSave(QDir(Settings::getSettingsDirPath()).filePath(profile + TOX_EXT));
|
||||
}
|
||||
return QByteArray();
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include "src/widget/toxuri.h"
|
||||
#include "src/widget/toxsave.h"
|
||||
#include "src/autoupdate.h"
|
||||
#include "src/profilelocker.h"
|
||||
#include <QApplication>
|
||||
#include <QCommandLineParser>
|
||||
#include <QDateTime>
|
||||
|
@ -213,6 +214,13 @@ int main(int argc, char *argv[])
|
|||
ipc.registerEventHandler("save", &toxSaveEventHandler);
|
||||
ipc.registerEventHandler("activate", &toxActivateEventHandler);
|
||||
|
||||
// If we're the IPC owner and we just started, then
|
||||
// either we're the only running instance or any other instance
|
||||
// is already so frozen it lost ownership.
|
||||
// It's safe to remove any potential stale locks in this situation.
|
||||
if (ipc.isCurrentOwner())
|
||||
ProfileLocker::clearAllLocks();
|
||||
|
||||
if (parser.positionalArguments().size() > 0)
|
||||
{
|
||||
QString firstParam(parser.positionalArguments()[0]);
|
||||
|
|
69
src/profilelocker.cpp
Normal file
69
src/profilelocker.cpp
Normal file
|
@ -0,0 +1,69 @@
|
|||
#include "profilelocker.h"
|
||||
#include "src/misc/settings.h"
|
||||
#include <QDir>
|
||||
#include <QDebug>
|
||||
|
||||
using namespace std;
|
||||
|
||||
unique_ptr<QLockFile> ProfileLocker::lockfile;
|
||||
QString ProfileLocker::curLockName;
|
||||
|
||||
QString ProfileLocker::lockPathFromName(const QString& name)
|
||||
{
|
||||
return Settings::getInstance().getSettingsDirPath()+'/'+name+".lock";
|
||||
}
|
||||
|
||||
bool ProfileLocker::isLockable(QString profile)
|
||||
{
|
||||
// If we already have the lock, it's definitely lockable
|
||||
if (lockfile && curLockName == profile)
|
||||
return true;
|
||||
|
||||
QLockFile newLock(lockPathFromName(profile));
|
||||
return newLock.tryLock();
|
||||
}
|
||||
|
||||
bool ProfileLocker::lock(QString profile)
|
||||
{
|
||||
if (lockfile && curLockName == profile)
|
||||
return true;
|
||||
|
||||
QLockFile* newLock = new QLockFile(lockPathFromName(profile));
|
||||
if (!newLock->tryLock())
|
||||
{
|
||||
delete newLock;
|
||||
return false;
|
||||
}
|
||||
|
||||
unlock();
|
||||
lockfile.reset(newLock);
|
||||
curLockName = profile;
|
||||
return true;
|
||||
}
|
||||
|
||||
void ProfileLocker::unlock()
|
||||
{
|
||||
if (!lockfile)
|
||||
return;
|
||||
lockfile->unlock();
|
||||
delete lockfile.release();
|
||||
lockfile = nullptr;
|
||||
curLockName.clear();
|
||||
}
|
||||
|
||||
void ProfileLocker::clearAllLocks()
|
||||
{
|
||||
qDebug() << "ProfileLocker::clearAllLocks: Wiping out all lock files";
|
||||
if (lockfile)
|
||||
unlock();
|
||||
|
||||
QDir dir(Settings::getInstance().getSettingsDirPath());
|
||||
dir.setFilter(QDir::Files);
|
||||
dir.setNameFilters({"*.lock"});
|
||||
QFileInfoList files = dir.entryInfoList();
|
||||
for (QFileInfo fileInfo : files)
|
||||
{
|
||||
QFile file(fileInfo.absoluteFilePath());
|
||||
file.remove();
|
||||
}
|
||||
}
|
40
src/profilelocker.h
Normal file
40
src/profilelocker.h
Normal file
|
@ -0,0 +1,40 @@
|
|||
#ifndef PROFILELOCKER_H
|
||||
#define PROFILELOCKER_H
|
||||
|
||||
#include <QLockFile>
|
||||
#include <memory>
|
||||
|
||||
/// Locks a Tox profile so that multiple instances can not use the same profile.
|
||||
/// Only one lock can be acquired at the same time, which means
|
||||
/// that there is little need for manually unlocking.
|
||||
/// The current lock will expire if you exit or acquire a new one.
|
||||
class ProfileLocker
|
||||
{
|
||||
private:
|
||||
ProfileLocker()=delete;
|
||||
|
||||
public:
|
||||
/// Checks if a profile is currently locked by *another* instance
|
||||
/// If we own the lock, we consider it lockable
|
||||
/// There is no guarantee that the result will still be valid by the
|
||||
/// time it is returned, this is provided on a best effort basis
|
||||
static bool isLockable(QString profile);
|
||||
/// Tries to acquire the lock on a profile, will not block
|
||||
/// Returns true if we already own the lock
|
||||
static bool lock(QString profile);
|
||||
/// Releases the lock on the current profile
|
||||
static void unlock();
|
||||
/// Releases all locks on all profiles
|
||||
/// DO NOT call unless all we're the only qTox instance
|
||||
/// and we don't hold any lock yet.
|
||||
static void clearAllLocks();
|
||||
|
||||
private:
|
||||
static QString lockPathFromName(const QString& name);
|
||||
|
||||
private:
|
||||
static std::unique_ptr<QLockFile> lockfile;
|
||||
static QString curLockName;
|
||||
};
|
||||
|
||||
#endif // PROFILELOCKER_H
|
Loading…
Reference in New Issue
Block a user