У меня есть приложение Linux C ++, которое порождает и взаимодействует с другим процессом через Unix Domain Socket. Этот новый процесс, в основном, просто отображает значок процесса, запущенного в данный момент на панели задач, а некоторые элементы меню отображаются на значке.
Проблема:
Когда основное приложение закрыто изящно, файл UDS удаляется.
Но в случае сбоя приложения этот файл UDS не удаляется и он сохраняется.
Есть ли способ удалить файл UDS при сбое приложения через кодирование?
Есть ли способ удалить файл UDS при сбое приложения через кодирование?
Да. Несколько способов в зависимости от того, насколько хорошо вы используете потенциально не переносимые возможности или нет.
Используя отдельный процесс:
Используйте отдельный процесс для мониторинга вашего приложения; возможно, тот, который вы написали для этой цели. Когда этот процесс мониторинга обнаруживает, что ваше приложение завершилось, он проверяет файл сокета домена Unix. Если найдено, он удаляет его. Затем он перезапускает приложение (при необходимости).
Используя «абстрактный сокет»:
Я считаю, что вы также можете использовать «абстрактный сокет», хотя я сам не пробовал.
Онлайн Страница руководства linux для доменного сокета Unix описывает расширение под названием «абстрактные сокеты». Это объясняет, что: «Абстрактные сокеты автоматически исчезают, когда закрыты все открытые ссылки на сокет».
Используя «семантику»:
На основе Linux Страница руководства по сокету домена Unix В разделе notes утверждается: «Применяется обычная семантика UNIX; сокет может быть отсоединен в любое время и будет окончательно удален из файловой системы после закрытия последней ссылки на него». То есть вызов bind
чтобы создать сокет, дождитесь подключения клиента, затем unlink
сокет, а затем идти с кодом, который может произойти сбой. Однако после удаления сокета из записи каталога новые попытки подключения клиента завершатся неудачно.
Использование потенциального обходного пути
использование SO_REUSEADDR
на вашем сокете до вашего bind
вызов. Это может позволить приложению перезапуститься без необходимости удаления сокета. Я не знаю, хорошо ли это поведение определено для сокетов Unix. Он может работать на одной платформе, но не на другой.
Проблема: Когда основное приложение закрыто изящно, файл UDS удаляется. Но в случае сбоя приложения этот файл UDS не удаляется и он сохраняется.
Другой способ обработки файла сокета домена Unix (его переносная / стандартная версия) — это удалить файл сокета в вашем приложении, прежде чем он приступит к его созданию. Поэтому, прежде чем ваше приложение звонит bind
это будет использовать unlink
, Пока это единственный процесс, который будет создавать этот файл, все должно быть copacetic w.r.t. избегая гонок.
Остерегайтесь, хотя, используя unlink
может открыть потенциальную уязвимость безопасности, если ваше приложение запускается с повышенными привилегиями (например, используя возможность set-user-ID для запуска от имени root). Затем убедитесь, что пользователь не может сообщить приложению, какой путь использовать для сокета, и что ни один из каталогов, в которых будет находиться сокет, не может быть изменен пользователем. В противном случае пользователь может сообщить приложению, что полный путь сокета был /etc/passwd
и запустите его, чтобы удалить этот файл, даже если сам пользователь не имел права делать это.
Этот потенциал повреждения, конечно, смягчается такими вещами, как использование учетной записи с наименьшими привилегиями для привилегии set-user-ID или избеганием set-user-ID вместе. Другим смягчением было бы запретить пользователю указывать приложению, какой путь использовать для его сокета, например, просто используя жестко заданное имя пути, для которого у пользователя не будет никаких прав записи ни в один из своих каталогов.
Не уверен, что это поможет, но вы можете обнаружить и осиротевший сокет Unix.
Вы можете попробовать заблокировать файл или сокет при запуске. Если блокировка успешна, это означает, что сокет потерян и может быть удален. Это происходит потому, что блокировки файлов снимаются ОС, когда процесс прекращается по любой причине.
С другой стороны, bind
в этот сокет Unix. bind
Успешно, только если имя сокета не используется.