Как освободить дескриптор сокета, совместно используемый несколькими процессами? - PullRequest
0 голосов
/ 25 октября 2018

Фон

В Linux или BSD можно отправлять дескрипторы для открытия файлов или сокетов между несвязанными процессами с SCM_RIGHTS, и у меня это работает, например, что в процессепрослушивает соединения, а затем перенаправляет дескрипторы процессу, который выполняет связь.

Проблема

Я не могу понять, как освободить дескриптор сокета отпроцесс прослушивания без отключения сокета.

В man close(3) имеется два конфликтующих описания:

Когда все дескрипторы файлов, связанные с описанием открытого файла, были закрыты, открытое окноописание файла должно быть освобождено.

И

Если fildes относится к сокету, close () приведет к его разрушению.

Первоначально я думал, что это означает, что вызов close() просто уменьшит счетчик ссылок для объекта ядра, который имеет сокет, так что последнее описание из man close(3) означало «уничтожить, когда последний дескриптор закрыт».

РЕДАКТИРОВАТЬ: Вот как это должно работать, а также как это работает.

Но, когда я запускаю тесты, кажется, что, как только я вызываю close() в дескрипторе сокета в процессе прослушивания он начнет закрывать сокет, отправляя либо RST, либо FIN, в зависимости от того, что другой процесс в данный момент делает с сокетом.

Одно решениебыло бы иметь обратный вызов от процесса передачи с «теперь вы можете закрыть сокет nnn», но это будет держать ряд дескрипторов сокетов открытыми в процессе прослушивания и добавить некоторые издержки.

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

Я предполагаю, что существует простое решение, но я не могу его найти.

Вопрос

Есть ли способ отменить регистрацию дескриптора сокета в процессе прослушивания, чтобы его больше не было в таблице файловых дескрипторов процесса,но без активации отключения сокета?

Исходный код

Реализация SCM_RIGHTS, используемая для отправки сокета, находится здесь (send_fds иnative_close):

Код, который отправляет сокет и затем закрывает его, находится здесь:

Если я закомментирую строку 497, все будет работать, но, очевидно, получится большая утечка файловых дескрипторов.

Получающий конец SCM_RIGHTS находится здесь:

1 Ответ

0 голосов
/ 25 октября 2018

tl; dr: сокет закрывается при закрытии последней ссылки.

Скорее всего, ответ на мой вопрос:

Нет, нет способа предотвратитьвыключение сокета, но это не нужно, так как сокет не закроется, пока не закроется последний дескриптор.

Ответ от Эндрю был верным, и я понял, что нет смысла, другиеделайте то же самое все время.

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

Когда я остановил вызов close() из процесса прослушивания, он начал работать.Это происходит потому, что тайм-аут корректно закрывает дескриптор, но в процессе прослушивания все еще есть ссылка, поэтому сокет остается открытым.

...