From e67cf96250db8d1d11dc860d664a4b0682e8f39e Mon Sep 17 00:00:00 2001 From: cc9cii Date: Fri, 5 Dec 2014 01:09:42 +1100 Subject: [PATCH] Allow only one instance of OpenCS. Only tested on windows x64. --- apps/opencs/editor.cpp | 57 +++++++++++++++++++++++++++++++++++++++--- apps/opencs/editor.hpp | 4 +++ apps/opencs/main.cpp | 2 +- 3 files changed, 59 insertions(+), 4 deletions(-) diff --git a/apps/opencs/editor.cpp b/apps/opencs/editor.cpp index bef83b8ac..dc4044fea 100644 --- a/apps/opencs/editor.cpp +++ b/apps/opencs/editor.cpp @@ -22,7 +22,7 @@ CS::Editor::Editor (OgreInit::OgreInit& ogreInit) : mUserSettings (mCfgMgr), mOverlaySystem (0), mDocumentManager (mCfgMgr), mViewManager (mDocumentManager), mPhysicsManager (0), - mIpcServerName ("org.openmw.OpenCS"), mServer(NULL), mClientSocket(NULL) + mIpcServerName ("org.openmw.OpenCS"), mServer(NULL), mClientSocket(NULL), mPid(""), mLock() { std::pair > config = readConfig(); @@ -70,7 +70,10 @@ CS::Editor::Editor (OgreInit::OgreInit& ogreInit) } CS::Editor::~Editor () -{} +{ + if(mServer && boost::filesystem::exists(mPid)) + remove(mPid.string().c_str()); // ignore error +} void CS::Editor::setupDataFiles (const Files::PathContainer& dataDirs) { @@ -233,7 +236,54 @@ void CS::Editor::showSettings() bool CS::Editor::makeIPCServer() { - mServer = new QLocalServer(this); + try + { + mPid = boost::filesystem::temp_directory_path(); + mPid += "opencs.pid"; + bool pidExists = boost::filesystem::exists(mPid); + + boost::filesystem::ofstream tempFile(mPid); + + mLock = boost::interprocess::file_lock(mPid.string().c_str()); + if(!mLock.try_lock()) + { + std::cerr << "OpenCS already running." << std::endl; + return false; + } + +#ifdef _WIN32 + tempFile << GetCurrentProcessId() << std::endl; +#else + tempFile << getpid() << std::endl; +#endif + tempFile.close(); + + mServer = new QLocalServer(this); + + if(pidExists) + { + // hack to get the temp directory path + mServer->listen("dummy"); + QString fullPath = mServer->fullServerName(); + mServer->close(); + fullPath.remove(QRegExp("dummy$")); + fullPath += mIpcServerName; + if(boost::filesystem::exists(fullPath.toStdString().c_str())) + { + // TODO: compare pid of the current process with that in the file + std::cout << "Detected unclean shutdown." << std::endl; + // delete the stale file + if(remove(fullPath.toStdString().c_str())) + std::cerr << "ERROR removing stale connection file" << std::endl; + } + } + } + + catch(const std::exception& e) + { + std::cerr << "ERROR " << e.what() << std::endl; + return false; + } if(mServer->listen(mIpcServerName)) { @@ -242,6 +292,7 @@ bool CS::Editor::makeIPCServer() } mServer->close(); + mServer = NULL; return false; } diff --git a/apps/opencs/editor.hpp b/apps/opencs/editor.hpp index d55b0e873..c8a6c43c3 100644 --- a/apps/opencs/editor.hpp +++ b/apps/opencs/editor.hpp @@ -3,6 +3,8 @@ #include +#include + #include #include #include @@ -54,6 +56,8 @@ namespace CS CSVDoc::FileDialog mFileDialog; boost::filesystem::path mLocal; boost::filesystem::path mResources; + boost::filesystem::path mPid; + boost::interprocess::file_lock mLock; bool mFsStrict; void setupDataFiles (const Files::PathContainer& dataDirs); diff --git a/apps/opencs/main.cpp b/apps/opencs/main.cpp index b184a1ef1..dd20324d1 100644 --- a/apps/opencs/main.cpp +++ b/apps/opencs/main.cpp @@ -83,7 +83,7 @@ int main(int argc, char *argv[]) if(!editor.makeIPCServer()) { editor.connectToIPCServer(); - // return 0; + return 0; } shinyFactory = editor.setupGraphics();