Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Как получить доступ к объекту другого приложения, если получен адрес этого объекта
Форум на CrossPlatform.RU > Библиотеки > Qt > Qt Ввод/Вывод, Сеть. Межпроцессное взаимодействие
MishaUA
Здравствуйте!
Делаю в программе защиту от повторного запуска. Идея следующая - если запускаем программу второй раз, каким-то образом делаем активным окно первого экземпляра(activateWindow()) и выходим.
Отслеживание повторного запуска сделал с помощью QSharedMemory. После запуска в его data() записывается указатель на QMainWindow приложения, но если оказалось, что программа запущена повторно, тогда через QSharedMemory->data() получаем указатель на QMainWindow первого экземпляра и вызываем у него activateWindow().
Собственно, при повторном запуске прога начала вылетать. Где я протупил догло искать не пришлось - в data() же был записан указатель на объект, который находится в области памяти первого экземпляра приложения и так просто к нему достучаться нельзя.
Не подскажете, как можно решить данную проблему?
lanz
Записывайте в общую память флаг "активируйся!". И пусть приложение опрашивает этот флаг. Как только он поднят, вызываем activateWindow, сбрасываем флаг.
wiz29
Как вариант можно использовать именованный канал (pipe). Если экземпляру приложения не удалось подключиться к созданному каналу, то оно создает такой канал и считает, что это 1й экземпляр приложения.
Когда обнаруживается повторный запуск, 2й экземпляр спокойно подключается к данному каналу и отправляет нужную команду основному приложению. Такую схему так же удобно использовать для открытия файла по клику в Windows системах когда нужно иметь только 1 экземпляр приложения. В команде в этом слаче передается путь к файлу, который надо открыть.
MishaUA
Сделал как написал lanz. По-моему, эт самый простой способ
lanz
То что предложил wiz29 эквивалентно (с точностью до изоморфизма :lol: ), разница в транспорте сообщения только. Поэтому если реализовано сообщение через общую память, то проще.
Iron Bug
обычно отслеживание запуска нескольких экземпляров приложения реализуют с помощью именованных мьютексов. это самый стандартный метод. а активация окна может производиться любым методом межпроцессного взаимодействия (например, через отправку сигналов).
lanz
Насколько я помню, именованные мьютексы под линукс не освобождаются если процесс крашится, поэтому не очень удобно.
Iron Bug
Цитата(lanz @ 4.12.2015, 1:54) *
Насколько я помню, именованные мьютексы под линукс не освобождаются если процесс крашится, поэтому не очень удобно.

в любой системе это так. потому что мьютекс не принадлежит процессу, это объект ядра. просто не надо писать приложения, которые крашатся :)
lanz
Цитата
просто не надо писать приложения, которые крашатся

Вот и мой начальник так говорит все время :lol:

Меня смутила секция Platform-Specific Behaviour вот отсюда:
http://doc.qt.io/qt-4.8/qsystemsemaphore.html
Цитата
Windows: QSystemSemaphore does not own its underlying system semaphore. Windows owns it. This means that when all instances of QSystemSemaphore for a particular key have been destroyed, either by having their destructors called, or because one or more processes crash, Windows removes the underlying system semaphore.

и
Цитата
Unix:
QSystemSemaphore owns the underlying system semaphore in Unix systems. This means that the last process having an instance of QSystemSemaphore for a particular key must remove the underlying system semaphore in its destructor. If the last process crashes without running the QSystemSemaphore destructor, Unix does not automatically remove the underlying system semaphore, and the semaphore survives the crash.

Правда если внимательно читать:
Цитата
When a process using QSystemSemaphore terminates for any reason, Unix automatically reverses the effect of all acquire operations that were not released. Thus if the process acquires a resource and then exits without releasing it, Unix will release that resource.

Таким образом и Win и Unix отпускают захваченные мьютексы, просто Windows удаляет его сам когда завершается/крашится последний процесс, а в Unix этого не происходит.
Цитата
To protect against this, the first process to create a semaphore for a particular key (usually a server), must pass its access mode as Create, which will force Unix to reset the resource count in the underlying system semaphore.


Насколько я понимаю с точки зрения захвата/освобождения все одинаково, единственная разница в ownership, но это уже вкусовщина.
wiz29
Цитата(Iron Bug @ 3.12.2015, 23:12) *
обычно отслеживание запуска нескольких экземпляров приложения реализуют с помощью именованных мьютексов. это самый стандартный метод. а активация окна может производиться любым методом межпроцессного взаимодействия (например, через отправку сигналов).


Это допустить можно, однако мир не идеален и это для B2C не очень удачное решение, в случае если приложение развалится. (пользователю потом не объяснишь, что надо ОС перезапустить чтоб перезапустить программу) Для OS X напрример можно записать в файл настроек ID процесса и его проверять при запуске. Для nix систем подозреваю можно сделать тоже самое. Такое решение более надежно в этом случае. Но вариантов решения 1 и той же задачи всегда много.
Iron Bug
я не понимаю, о чём вообще разговор. программирую уже более 20 лет. всякие области применения были: и микроконтроллеры, и промышленная автоматика, управление железом в риалтайме, и серверные приложения, которые работают без перерыва годами, и кернельные модули, и драйверы. всё под разные системы или кроссплатформу. и как-то нигде не возникало проблем, ничего не падало.
просто думать надо головой, когда код пишешь. и тестировать тщательно.

что касается линюкса, то если семафор по каким-то причинам "завис", то его можно сбросить утилитой ipcrm.
в posix именованному мьютексу можно установить флаг PTHREAD_MUTEX_ROBUST и тогда после ненормального завершения потока его хэндлер закроется системой.
в венде лучше использовать мьютексы, на них хэндлы всегда закрываются после завершения потока. соответственно, в кроссплатформе тоже лучше использовать мьютексы.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Форум IP.Board © 2001-2018 IPS, Inc.