Отключить/очистить сокет unix, только если он все еще принадлежит процессу

Первый раз работаю с сокетами домена Unix, теперь я пытаюсь реализовать часть очистки.

Уже казалось немного уродливым, что общая рекомендация при создании сокета для прослушивания — сначала попытаться отменить связь с желаемым путем сокета, а затем вызвать привязку. Хотя вам, вероятно, следует убедиться, что ваш процесс запускается только один раз, я пытаюсь подготовиться к ситуации, когда по какой-то причине он будет запущен дважды. Для самой службы это не имеет большого значения: сокет первого экземпляра не связан вторым экземпляром, поэтому он недоступен, тратит немного оперативной памяти, но не причиняет никакого вреда. Но как мне реализовать очистку, которая работает в этой ситуации? Просто делать

close(sockFd);
unlink(sockPath);

приведет к тому, что если первый процесс завершится, пока второй все еще работает, он фактически удалит сокет второго процесса из файловой системы. Бум, без сервиса.

Я могу думать только о нескольких уродливых хаках, которые не были бы атомарными, поэтому все еще могли все испортить, поэтому я надеюсь, что есть лучшая парадигма, чтобы предотвратить попадание в эту ситуацию. Что-то вроде funlink(sockFd) было бы неплохо. В противном случае мне пришлось бы никогда не чистить сокет, что не является концом света, но мне кажется довольно грязным.

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


person Simon    schedule 25.02.2016    source источник
comment
Вот что я обычно делаю, чтобы избежать двух процессов, пытающихся прослушивать один и тот же сокет домена unix. Первое, что я делаю, это пытаюсь подключиться к сокету. Если соединение работает, прослушиватель уже запущен, я выручаю. В противном случае я позволю процессу продолжиться и прослушаю сокет. Очистка должна быть легкой, потому что вы уверены, что у вас есть только 1 слушатель.   -  person alvits    schedule 26.02.2016
comment
Однако правильный подход заключается в попытке привязаться к сокету, и вы получите EADDRINUSE, если сокет уже используется. Теперь, когда вы знаете, что другой процесс уже прослушивает его, вы можете выйти из него.   -  person alvits    schedule 26.02.2016
comment
@alvits Я думаю, вы получаете ‹code›EADDRINUSE‹/code›, даже если первый процесс завершился и в файловой системе остался только устаревший сокет, так что это не лучше, чем безоговорочно удалить сокет при запуске, но соединение перед привязкой может быть вариантом; Я попробую немного...   -  person Simon    schedule 26.02.2016


Ответы (1)


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

person Marcus    schedule 25.02.2016