Здравствуйте, korsakovs, Вы писали:
K>1. Запрет запуска второй копии приложения
Как вариант:
Microsoft советует в таких случаях создавать в %TEMP% каталоге файл и анализировать его. Доступ для этого файла — только чтение.
Я, например, там храню HWND окна уже запущенного приложения что бы можно было его показать.
K>2. Надо реализовать MemoryMappedFile. K>Вопрос в том, реально ли это сделать в Qt4 не используя системные функции Windows???
Можно попытатся пройти по сырцах Qt4 в поисках MemoryMappedFile, а там уже выйты на высокоуровневые межплатформенные враперы.
Здравствуйте, korsakovs, Вы писали:
K>Я написал программу на Qt4 к которой мне нужно добаыить 2 требования:
K>1. Запрет запуска второй копии приложения K>Не могу найти в help'e как это реализовать...
Я писал свой враппер (работает на Win/*nix)
SysNamedSingletonException.h
#ifndef SYSNAMEDSINGLETON_H
#define SYSNAMEDSINGLETON_H
#include <string>
#include <stdexcept>
struct SysNamedSingletonException : std::logic_error
{
explicit SysNamedSingletonException(const std::string& aMessage = "") : std::logic_error(aMessage) {}
};
class SysNamedSingleton
{
public:
// throw SysNamedSingletonException on error
SysNamedSingleton(const std::string& aName);
~SysNamedSingleton();
// Return: true if the system-wide singletone with the name has been created
// false if the singleton with such name already exists in the systembool isCreated() const;
private:
struct SysNamedSingletonExceptionImpl;
SysNamedSingletonExceptionImpl* theImplPtr;
};
#endif
SysNamedSingleton.cpp
struct SysNamedSingleton::SysNamedSingletonExceptionImpl
{
SysNamedSingletonExceptionImpl(const std::string& aSemName)
: theHandle(0)
, theSemName(aSemName)
{}
#ifndef _WIN32
typedef sem_t * HANDLE;
#endif
HANDLE theHandle;
std::string theSemName;
};
SysNamedSingleton::SysNamedSingleton(const std::string& aName)
: theImplPtr(new SysNamedSingletonExceptionImpl(aName))
{
#ifdef _WIN32
HANDLE myHandle = ::CreateMutex(NULL, TRUE, aName.c_str());
if (!myHandle)
throw(SysNamedSingletonException("Failed to create a mutex with name " + aName));
if (::GetLastError() == ERROR_ALREADY_EXISTS)
return;
#else
sem_t* myHandle = sem_open(aName.c_str(), O_CREAT|O_EXCL, S_IRWXU|S_IRWXG|S_IRWXO, 1);
if ((int)myHandle == SEM_FAILED)
{
if (errno == EEXIST)
return;
throw(SysNamedSingletonException("Failed to create a semaphore with name" + aName);
}
#endif
theImplPtr->theHandle = myHandle;
}
SysNamedSingleton::~SysNamedSingleton()
{
if (theImplPtr->theHandle)
{
#ifdef _WIN32
::CloseHandle(theImplPtr->theHandle);
#else
if (sem_unlink(theImplPtr->theSemName.c_str()) == 0)
sem_close(theImplPtr->theHandle);
#endif
}
delete theImplPtr;
}
bool SysNamedSingleton::isCreated() const
{
return !!theImplPtr->theHandle;
}
Здравствуйте, Андрей Коростелев, Вы писали:
АК>Я писал свой враппер (работает на Win/*nix)
Что мне не нравится в твоем коде — если твоя аппликуха выпадет по SIGSEGV, то запустить вторую копию проги будет проблематично
Обычно это все таки решают с помощью временного файла, в который пишут PID процесса, который потом и анализируют на существование и которому опять же шлют сигналы если нужно активировать запущенную копию аппликухи.
Здравствуйте, Garrrrr, Вы писали:
G>Здравствуйте, Андрей Коростелев, Вы писали:
АК>>Я писал свой враппер (работает на Win/*nix)
G>Что мне не нравится в твоем коде — если твоя аппликуха выпадет по SIGSEGV, то запустить вторую копию проги будет проблематично G>Обычно это все таки решают с помощью временного файла, в который пишут PID процесса, который потом и анализируют на существование и которому опять же шлют сигналы если нужно активировать запущенную копию аппликухи.
Ага, уже и сам заметил. Спасибо, что указал тем не менее.
Здравствуйте, astral_marine, Вы писали:
_>Как вариант: _>Microsoft советует в таких случаях создавать в %TEMP% каталоге файл и анализировать его. Доступ для этого файла — только чтение. _>Я, например, там храню HWND окна уже запущенного приложения что бы можно было его показать.
Это все конечно хорошо, но вот что непонятно, будет ли этот файл уничтожаться допустим при уничтожении процесса или при нажатии на reset. Я думал, что в Qt есть что-нибудь для облегчения этой проблемы.
_>Можно попытатся пройти по сырцах Qt4 в поисках MemoryMappedFile, а там уже выйты на высокоуровневые межплатформенные враперы.
Здравствуйте, Garrrrr, Вы писали:
G>Здравствуйте, Андрей Коростелев, Вы писали:
АК>>Я писал свой враппер (работает на Win/*nix)
G>Что мне не нравится в твоем коде — если твоя аппликуха выпадет по SIGSEGV, то запустить вторую копию проги будет проблематично G>Обычно это все таки решают с помощью временного файла, в который пишут PID процесса, который потом и анализируют на существование и которому опять же шлют сигналы если нужно активировать запущенную копию аппликухи.
А кто будет временный файл удалять при падении процесса?
Здравствуйте, McQwerty, Вы писали:
MQ>Здравствуйте, Garrrrr, Вы писали:
G>>Обычно это все таки решают с помощью временного файла, в который пишут PID процесса, который потом и анализируют на существование и которому опять же шлют сигналы если нужно активировать запущенную копию аппликухи.
MQ>А кто будет временный файл удалять при падении процесса?
Его удалять необязательно, потому как по завершению процесса нем останется pid несуществующего (в частном случае: упавшего) процесса. И новый экземпляр програмы, убедившись, что процесса с данным pid нет среди запущенных, сможет успешно стартовать.
Тут однако есть небольшое "но": потому как множество pid процессов конечно, рано или поздно системе придется выдать новому созданному процессу pid когда-то уже существовавшего и завершившегося процесса. Которым может оакзаться и pid нашей программы. Вероятность такого рода совпадения этого не так чтобы велика, но и не нулевая. Потому чтобы ее еще уменьшить, лучше этот файл очищать при нормальном завершении программы.
Здравствуйте, Андрей Коростелев, Вы писали:
АК>Его удалять необязательно, потому как по завершению процесса нем останется pid несуществующего (в частном случае: упавшего) процесса. И новый экземпляр програмы, убедившись, что процесса с данным pid нет среди запущенных, сможет успешно стартовать.
АК>Тут однако есть небольшое "но": потому как множество pid процессов конечно, рано или поздно системе придется выдать новому созданному процессу pid когда-то уже существовавшего и завершившегося процесса. Которым может оакзаться и pid нашей программы. Вероятность такого рода совпадения этого не так чтобы велика, но и не нулевая. Потому чтобы ее еще уменьшить, лучше этот файл очищать при нормальном завершении программы.
Здравствуйте, Андрей Коростелев, Вы писали:
АК>Его удалять необязательно, потому как по завершению процесса нем останется pid несуществующего (в частном случае: упавшего) процесса. И новый экземпляр програмы, убедившись, что процесса с данным pid нет среди запущенных, сможет успешно стартовать.
АК>Тут однако есть небольшое "но": потому как множество pid процессов конечно, рано или поздно системе придется выдать новому созданному процессу pid когда-то уже существовавшего и завершившегося процесса. Которым может оакзаться и pid нашей программы. Вероятность такого рода совпадения этого не так чтобы велика, но и не нулевая. Потому чтобы ее еще уменьшить, лучше этот файл очищать при нормальном завершении программы.
Да и это не обязательно. Наряду с PID можно проверить и ассоциированную с этим PID имя программы. Вероятность такого рода совпадений практически 0.
Большую опасность представляют программы-зомби
Здравствуйте, Garrrrr, Вы писали:
G>Здравствуйте, Андрей Коростелев, Вы писали:
АК>>Его удалять необязательно, потому как по завершению процесса нем останется pid несуществующего (в частном случае: упавшего) процесса. И новый экземпляр програмы, убедившись, что процесса с данным pid нет среди запущенных, сможет успешно стартовать.
АК>>Тут однако есть небольшое "но": потому как множество pid процессов конечно, рано или поздно системе придется выдать новому созданному процессу pid когда-то уже существовавшего и завершившегося процесса. Которым может оакзаться и pid нашей программы. Вероятность такого рода совпадения этого не так чтобы велика, но и не нулевая. Потому чтобы ее еще уменьшить, лучше этот файл очищать при нормальном завершении программы. G>Да и это не обязательно. Наряду с PID можно проверить и ассоциированную с этим PID имя программы. Вероятность такого рода совпадений практически 0.
Я собственно так и сделал: потому как нас интересует конкретная программа, для хранения pid удобно использовать файл с таким же названием, как и у программы. Вероятность переименования программы не учитываем: на машине пользователя, например, это при желании легко разруливается программой-инсталлятором.
Плюс к этому, если нужно разрешить по одному экземпляру на пользователя (а не вообще глобально-системно), файл с pid помещается в пользовательской каталог.
G>Большую опасность представляют программы-зомби
+1
Здравствуйте, Garrrrr, Вы писали:
G>Здравствуйте, Андрей Коростелев, Вы писали:
АК>>Я писал свой враппер (работает на Win/*nix)
G>Что мне не нравится в твоем коде — если твоя аппликуха выпадет по SIGSEGV, то запустить вторую копию проги будет проблематично :) G>Обычно это все таки решают с помощью временного файла, в который пишут PID процесса, который потом и анализируют на существование и которому опять же шлют сигналы если нужно активировать запущенную копию аппликухи.
Добавлю — что для Unix файл этот лучше всё время работы лочить flock'ом (кроме случая его размещения на NFS, но это нечасто).
Здравствуйте, netch80, Вы писали: N>Добавлю — что для Unix файл этот лучше всё время работы лочить flock'ом (кроме случая его размещения на NFS, но это нечасто).
Я бы не стал утверждать что нечасто. Во всех конторах домашняя директория маунитится через NFS. Хотя, конечно, такие файлы логичнее класть в /tmp чем в ~/.
"To protect people you must slay people. To let people live you must let people die. This is the true teaching of the sword."
-Seijuro Hiko, "Rurouni Kensin"