Фон
В 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
находится здесь: