2010-09-02 3 views

ответ

7

Убедитесь, что все дескрипторы файлов для сокета были закрыты. Если кто-либо остается открытым на «удаленном конце» (при условии, что это тот, который вы пытаетесь закрыть), «peer has not performed an orderly shutdown».

Если это не работает, позвоните по номеру shutdown(sock, SHUT_RDWR) на удаленном конце, это отключит сокет, независимо от количества ссылок.

11

«Почему» - это просто то, как это работает, по дизайну.

В ядре, recv() вызова называется fget() на struct file, соответствующий дескриптор файла, и это помешает ему не быть высвобождено до соответствующего fput().

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


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

+0

Если я вызываю close перед вызовом recv, он должен работать, но как только вызов находится в recv, и если я вызову close из другого потока, он не будет освобожден. Это верно? – Jay

+6

@Jay: После того, как вы вызвали 'close()', вы должны * не * вызывать 'recv()' в дескрипторе файла. Если вам повезет, вы просто получите «EBADF», но если вам не повезло, вы можете прочитать из совершенно другого сокета, недавно открытого другим потоком. – caf

+0

Думаю, вам не хватает смысла. Патер пытается вызвать close() в сокете, который является УЖЕ внутри recv(), чтобы заставить recv() выйти немедленно. Это работает на других системах, но не работает в Linux. –

Смежные вопросы