2 вопроса по Qt
От: korsakovs Россия  
Дата: 10.04.07 06:49
Оценка:
Я написал программу на Qt4 к которой мне нужно добаыить 2 требования:

1. Запрет запуска второй копии приложения
Не могу найти в help'e как это реализовать...

2. Надо реализовать MemoryMappedFile.
Вопрос в том, реально ли это сделать в Qt4 не используя системные функции Windows???

Может ли кто помочь?

20.01.10 20:38: Перенесено модератором из 'C/C++. Прикладные вопросы' — Кодт
Re: 2 вопроса по Qt
От: astral_marine  
Дата: 10.04.07 07:35
Оценка:
Здравствуйте, korsakovs, Вы писали:

K>1. Запрет запуска второй копии приложения


Как вариант:
Microsoft советует в таких случаях создавать в %TEMP% каталоге файл и анализировать его. Доступ для этого файла — только чтение.
Я, например, там храню HWND окна уже запущенного приложения что бы можно было его показать.

K>2. Надо реализовать MemoryMappedFile.

K>Вопрос в том, реально ли это сделать в Qt4 не используя системные функции Windows???

Можно попытатся пройти по сырцах Qt4 в поисках MemoryMappedFile, а там уже выйты на высокоуровневые межплатформенные враперы.
Re: 2 вопроса по Qt
От: Андрей Коростелев Голландия http://www.korostelev.net/
Дата: 10.04.07 08:03
Оценка: -1
Здравствуйте, 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 system
      bool 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;
}


Использование (cxxtest):
int main()
{
    {
    SysNamedSingleton mySingleton1v1("/ThisIsSingleton1");
    TS_ASSERT_EQUALS(mySingleton1v1.isCreated(), true);
    SysNamedSingleton mySingleton1v2("/ThisIsSingleton1");
    TS_ASSERT_EQUALS(mySingleton1v2.isCreated(), false);

    SysNamedSingleton mySingleton2v1("/ThisIsSingleton2");
    TS_ASSERT_EQUALS(mySingleton2v1.isCreated(), true);
    }
    SysNamedSingleton mySingleton2v2("/ThisIsSingleton2");
    TS_ASSERT_EQUALS(mySingleton2v2.isCreated(), true);

    return 0;
}



K>Может ли кто помочь?
-- Андрей
Re[2]: 2 вопроса по Qt
От: Garrrrr  
Дата: 10.04.07 08:28
Оценка: 8 (1)
Здравствуйте, Андрей Коростелев, Вы писали:

АК>Я писал свой враппер (работает на Win/*nix)


Что мне не нравится в твоем коде — если твоя аппликуха выпадет по SIGSEGV, то запустить вторую копию проги будет проблематично
Обычно это все таки решают с помощью временного файла, в который пишут PID процесса, который потом и анализируют на существование и которому опять же шлют сигналы если нужно активировать запущенную копию аппликухи.
Re[3]: 2 вопроса по Qt
От: Андрей Коростелев Голландия http://www.korostelev.net/
Дата: 10.04.07 08:37
Оценка:
Здравствуйте, Garrrrr, Вы писали:

G>Здравствуйте, Андрей Коростелев, Вы писали:


АК>>Я писал свой враппер (работает на Win/*nix)


G>Что мне не нравится в твоем коде — если твоя аппликуха выпадет по SIGSEGV, то запустить вторую копию проги будет проблематично

G>Обычно это все таки решают с помощью временного файла, в который пишут PID процесса, который потом и анализируют на существование и которому опять же шлют сигналы если нужно активировать запущенную копию аппликухи.

Ага, уже и сам заметил. Спасибо, что указал тем не менее.
-- Андрей
Re[2]: 2 вопроса по Qt
От: Корсаков Сергей Россия  
Дата: 10.04.07 09:30
Оценка:
Здравствуйте, astral_marine, Вы писали:

_>Как вариант:

_>Microsoft советует в таких случаях создавать в %TEMP% каталоге файл и анализировать его. Доступ для этого файла — только чтение.
_>Я, например, там храню HWND окна уже запущенного приложения что бы можно было его показать.

Это все конечно хорошо, но вот что непонятно, будет ли этот файл уничтожаться допустим при уничтожении процесса или при нажатии на reset. Я думал, что в Qt есть что-нибудь для облегчения этой проблемы.

_>Можно попытатся пройти по сырцах Qt4 в поисках MemoryMappedFile, а там уже выйты на высокоуровневые межплатформенные враперы.


Можно, но времени вообще в обрез...
Re[3]: 2 вопроса по Qt
От: McQwerty Россия  
Дата: 13.04.07 17:35
Оценка:
Здравствуйте, Garrrrr, Вы писали:

G>Здравствуйте, Андрей Коростелев, Вы писали:


АК>>Я писал свой враппер (работает на Win/*nix)


G>Что мне не нравится в твоем коде — если твоя аппликуха выпадет по SIGSEGV, то запустить вторую копию проги будет проблематично

G>Обычно это все таки решают с помощью временного файла, в который пишут PID процесса, который потом и анализируют на существование и которому опять же шлют сигналы если нужно активировать запущенную копию аппликухи.

А кто будет временный файл удалять при падении процесса?
Re[4]: 2 вопроса по Qt
От: Андрей Коростелев Голландия http://www.korostelev.net/
Дата: 13.04.07 20:45
Оценка: 2 (1)
Здравствуйте, McQwerty, Вы писали:

MQ>Здравствуйте, Garrrrr, Вы писали:


G>>Обычно это все таки решают с помощью временного файла, в который пишут PID процесса, который потом и анализируют на существование и которому опять же шлют сигналы если нужно активировать запущенную копию аппликухи.


MQ>А кто будет временный файл удалять при падении процесса?


Его удалять необязательно, потому как по завершению процесса нем останется pid несуществующего (в частном случае: упавшего) процесса. И новый экземпляр програмы, убедившись, что процесса с данным pid нет среди запущенных, сможет успешно стартовать.

Тут однако есть небольшое "но": потому как множество pid процессов конечно, рано или поздно системе придется выдать новому созданному процессу pid когда-то уже существовавшего и завершившегося процесса. Которым может оакзаться и pid нашей программы. Вероятность такого рода совпадения этого не так чтобы велика, но и не нулевая. Потому чтобы ее еще уменьшить, лучше этот файл очищать при нормальном завершении программы.
-- Андрей
Re[5]: 2 вопроса по Qt
От: Корсаков Сергей Россия  
Дата: 14.04.07 09:38
Оценка:
Здравствуйте, Андрей Коростелев, Вы писали:

АК>Его удалять необязательно, потому как по завершению процесса нем останется pid несуществующего (в частном случае: упавшего) процесса. И новый экземпляр програмы, убедившись, что процесса с данным pid нет среди запущенных, сможет успешно стартовать.


АК>Тут однако есть небольшое "но": потому как множество pid процессов конечно, рано или поздно системе придется выдать новому созданному процессу pid когда-то уже существовавшего и завершившегося процесса. Которым может оакзаться и pid нашей программы. Вероятность такого рода совпадения этого не так чтобы велика, но и не нулевая. Потому чтобы ее еще уменьшить, лучше этот файл очищать при нормальном завершении программы.


А как в Qt4 получить PID процесса?
Re[6]: 2 вопроса по Qt
От: Андрей Коростелев Голландия http://www.korostelev.net/
Дата: 14.04.07 20:27
Оценка:
Здравствуйте, Корсаков Сергей, Вы писали:

КС>А как в Qt4 получить PID процесса?


QProcess::pid()
-- Андрей
Re[5]: 2 вопроса по Qt
От: Garrrrr  
Дата: 15.04.07 09:12
Оценка:
Здравствуйте, Андрей Коростелев, Вы писали:

АК>Его удалять необязательно, потому как по завершению процесса нем останется pid несуществующего (в частном случае: упавшего) процесса. И новый экземпляр програмы, убедившись, что процесса с данным pid нет среди запущенных, сможет успешно стартовать.


АК>Тут однако есть небольшое "но": потому как множество pid процессов конечно, рано или поздно системе придется выдать новому созданному процессу pid когда-то уже существовавшего и завершившегося процесса. Которым может оакзаться и pid нашей программы. Вероятность такого рода совпадения этого не так чтобы велика, но и не нулевая. Потому чтобы ее еще уменьшить, лучше этот файл очищать при нормальном завершении программы.

Да и это не обязательно. Наряду с PID можно проверить и ассоциированную с этим PID имя программы. Вероятность такого рода совпадений практически 0.
Большую опасность представляют программы-зомби
Re[6]: 2 вопроса по Qt
От: Андрей Коростелев Голландия http://www.korostelev.net/
Дата: 15.04.07 09:47
Оценка:
Здравствуйте, Garrrrr, Вы писали:

G>Здравствуйте, Андрей Коростелев, Вы писали:


АК>>Его удалять необязательно, потому как по завершению процесса нем останется pid несуществующего (в частном случае: упавшего) процесса. И новый экземпляр програмы, убедившись, что процесса с данным pid нет среди запущенных, сможет успешно стартовать.


АК>>Тут однако есть небольшое "но": потому как множество pid процессов конечно, рано или поздно системе придется выдать новому созданному процессу pid когда-то уже существовавшего и завершившегося процесса. Которым может оакзаться и pid нашей программы. Вероятность такого рода совпадения этого не так чтобы велика, но и не нулевая. Потому чтобы ее еще уменьшить, лучше этот файл очищать при нормальном завершении программы.

G>Да и это не обязательно. Наряду с PID можно проверить и ассоциированную с этим PID имя программы. Вероятность такого рода совпадений практически 0.

Я собственно так и сделал: потому как нас интересует конкретная программа, для хранения pid удобно использовать файл с таким же названием, как и у программы. Вероятность переименования программы не учитываем: на машине пользователя, например, это при желании легко разруливается программой-инсталлятором.

Плюс к этому, если нужно разрешить по одному экземпляру на пользователя (а не вообще глобально-системно), файл с pid помещается в пользовательской каталог.

G>Большую опасность представляют программы-зомби

+1
-- Андрей
Re[3]: 2 вопроса по Qt
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 21.04.07 09:34
Оценка:
Здравствуйте, Garrrrr, Вы писали:

G>Здравствуйте, Андрей Коростелев, Вы писали:


АК>>Я писал свой враппер (работает на Win/*nix)


G>Что мне не нравится в твоем коде — если твоя аппликуха выпадет по SIGSEGV, то запустить вторую копию проги будет проблематично :)

G>Обычно это все таки решают с помощью временного файла, в который пишут PID процесса, который потом и анализируют на существование и которому опять же шлют сигналы если нужно активировать запущенную копию аппликухи.

Добавлю — что для Unix файл этот лучше всё время работы лочить flock'ом (кроме случая его размещения на NFS, но это нечасто).
The God is real, unless declared integer.
Re[4]: 2 вопроса по Qt
От: Zigmar Израиль  
Дата: 22.04.07 08:23
Оценка:
Здравствуйте, 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"
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.