_ RU.UNIX (2:5077/15.22) _____________________________________________ RU.UNIX _
From : Anatoly A. Orehovsky 2:5020/400 03 Nov 99 07:54:06
Subj : как избежать CLOSE_WAIT
________________________________________________________________________________
From: tolik@mpeks.tomsk.su (Anatoly A. Orehovsky)
Eugene Crosser (crosser@average.org) wrote:
: Тут такая научная дискуссия по поводу TCP/IP - мне даже страшно
: вставиться со своим вопросом ;) А вопрос простой. Есть TCP-шный
: сервер, к нему обычно подсоединено несколько сессий от клиентов.
А какая у сервера ОС-то ? И клиентские, на всякий случай.
: Теперь, иногда этот сервер нужно бывает перезапустить. У него
: в обработчике SIGINT стоит цикл close() на все клиентские коннекции,
: и exit(). Так вот, не всегда, но довольно часто случается, что
По идее, по exit close должно бы отработать автоматически.
: процесс нормально завершается, клиенты на других машинах кончаются,
: а netstat показывает парочку коннекций в состоянии CLOSE_WAIT, и
: в такой позе они сидят несколько часов, и пока они так сидят, ни
: сервер снова не запустить (EADDRINUSE), и когда клиент пытается
: соединиться, он не получает ECONNREFUSED, а долго-долго ждет пока
: не истечет таймаут на connect. Мешает.
: Вопрос: как избежать такой ситуации? Hу кроме сокращения ядерного
: таймаута на это состояние. И вообще, когда оно возникает? Фраза
: из man netstat "The remote end has shut down, waiting for the
: socket to close" вроде бы мало соответствует действительности -
: сокет-то я давно закрыл. Или нет?
Вообще, в приведенной выдержке из man все правильно - в это состояние
из TCPS_ESTABLISHED или TCPS_SYN_RECEIVED переходит TCP FSM в момент
прихода FIN от peerа. То есть, например, когда клиент попытался
отвалится или зашутдаунил свою передачу раньше, чем сервер коннекцию
попытался закрыть или зашутдаунил передачу со своей стороны.
Hа действительно закрытом сокете, естественно, при правильной
ядреной реализации, этого состояния быть не должно. А был ли exit-то
? А не было ли forkа с висящим на коннекции потомком (очень похоже) ?
А насчет избежания ситуации - можно попробовать setsockopt(2) с SO_REUSE*.
--
Anatoly A. Orehovsky. AO9-RIPE. AAO1-RIPN
http://www.tekmetrics.com/transcript.shtml?pid=6064
--- ifmail v.2.14dev3
* Origin: CISA Ltd. InterNetNews site (2:5020/400)
_ RU.UNIX (2:5077/15.22) _____________________________________________ RU.UNIX _
From : Eugene Crosser 2:5020/400 05 Nov 99 01:12:08
Subj : как избежать CLOSE_WAIT
________________________________________________________________________________
From: crosser@average.org (Eugene Crosser)
In article <7vof22$37v@mpeks.tomsk.su>,
tolik@mpeks.tomsk.su (Anatoly A. Orehovsky) writes:
>: Тут такая научная дискуссия по поводу TCP/IP - мне даже страшно
>: вставиться со своим вопросом ;) А вопрос простой. Есть TCP-шный
>: сервер, к нему обычно подсоединено несколько сессий от клиентов.
>
> А какая у сервера ОС-то ? И клиентские, на всякий случай.
Solaris 2.5.1 и там и там. Что характерно, часто это случается
с соединением на самого себя (но не 127.0.0.1 а через эзернетовский
интерфейс).
>: Теперь, иногда этот сервер нужно бывает перезапустить. У него
>: в обработчике SIGINT стоит цикл close() на все клиентские коннекции,
>: и exit(). Так вот, не всегда, но довольно часто случается, что
>
> По идее, по exit close должно бы отработать автоматически.
Hу это просто на всякий случай.
>: процесс нормально завершается, клиенты на других машинах кончаются,
>: а netstat показывает парочку коннекций в состоянии CLOSE_WAIT, и
>: в такой позе они сидят несколько часов, и пока они так сидят, ни
>: сервер снова не запустить (EADDRINUSE), и когда клиент пытается
>: соединиться, он не получает ECONNREFUSED, а долго-долго ждет пока
>: не истечет таймаут на connect. Мешает.
>
>: Вопрос: как избежать такой ситуации? Hу кроме сокращения ядерного
>: таймаута на это состояние. И вообще, когда оно возникает? Фраза
>: из man netstat "The remote end has shut down, waiting for the
>: socket to close" вроде бы мало соответствует действительности -
>: сокет-то я давно закрыл. Или нет?
>
> Вообще, в приведенной выдержке из man все правильно - в это состояние
> из TCPS_ESTABLISHED или TCPS_SYN_RECEIVED переходит TCP FSM в момент
> прихода FIN от peerа. То есть, например, когда клиент попытался
> отвалится или зашутдаунил свою передачу раньше, чем сервер коннекцию
> попытался закрыть или зашутдаунил передачу со своей стороны.
То-то и оно, что процесса сервера давно уже нет, стало быть коннекцию
от заведомо закрыл (сам или при exit).
> Hа действительно закрытом сокете, естественно, при правильной
> ядреной реализации, этого состояния быть не должно. А был ли exit-то
> ? А не было ли forkа с висящим на коннекции потомком (очень похоже) ?
Hе, никаких потомков, там один процесс, читает сокеты через select.
Правда, есть потомки не имеющие отношения к сокету, но они все тоже
умирают после смерти отца, проверено. Вроде... А если нет, то может
в этом быть дело, да? Потомок ведь мог унаследовать открытый сокет,
а специально я его, кажется, не закрываю... И если потомок не умер,
может держать адрес. Hужно проверить.
> А насчет избежания ситуации - можно попробовать setsockopt(2) с SO_REUSE*.
Это само собой. Без него оно вообще каждый раз случается, а с ним -
только иногда.
Eugene
--- ifmail v.2.14dev3
* Origin: Average (2:5020/400)
_ RU.UNIX (2:5077/15.22) _____________________________________________ RU.UNIX _
From : Anatoly A. Orehovsky 2:5020/400 05 Nov 99 07:37:52
Subj : как избежать CLOSE_WAIT
________________________________________________________________________________
From: tolik@mpeks.tomsk.su (Anatoly A. Orehovsky)
Eugene Crosser (crosser@average.org) wrote:
: In article <7vof22$37v@mpeks.tomsk.su>,
: tolik@mpeks.tomsk.su (Anatoly A. Orehovsky) writes:
: > Hа действительно закрытом сокете, естественно, при правильной
: > ядреной реализации, этого состояния быть не должно. А был ли exit-то
: > ? А не было ли forkа с висящим на коннекции потомком (очень похоже) ?
: Hе, никаких потомков, там один процесс, читает сокеты через select.
: Правда, есть потомки не имеющие отношения к сокету, но они все тоже
: умирают после смерти отца, проверено. Вроде... А если нет, то может
: в этом быть дело, да? Потомок ведь мог унаследовать открытый сокет,
: а специально я его, кажется, не закрываю... И если потомок не умер,
: может держать адрес. Hужно проверить.
Проверить надо обязательно. И сообщить о результатах, если не трудно.
Конечно, потомок унаследует все открытые файловые дескрипторы. И
обязан тут же их закрыть, если они ему не нужны. Если потомок тут
же делает exec*(2,3), то можно обойтись и флагом close-on-exec
(fcntl(2)).
Гляньте по тексту - если у Вас потомок может образоваться ПОСЛЕ
того, как клиент закрыл свою сторону коннекции, но ДО того, как
сервер закрыл свою, пожалуй, может и получиться висячий CLOSE_WAIT.
Во всяком случае, во FreeBSD CLOSE_WAIT нет проблем достичь именно таким
образом. Да, а при коннекте на самогО себя не болтается ли при этом еще и
остаток соединения на порт сервера в состоянии FIN_WAIT_2 ? Должно
болтаться.
А потомок может быть плохо виден из-за execов (особенно, с setsid(2)),
например. Я не в курсе, можно ли найти владельца CLOSE_WAIT в solaris, как
во FreeBSD sockstat или netstat -Afinet; fstat ?
Кстати, а на чем основывается Ваша уверенность в смерти потомков
после смерти родителя ? Вы используете какой-то метод IPC или
мониторите родителя потомками ? А если родитель аварийно завершился
? Или потомок делал fork(2) и/или exec*(2,3) ?
: > А насчет избежания ситуации - можно попробовать setsockopt(2) с SO_REUSE*.
: Это само собой. Без него оно вообще каждый раз случается, а с ним -
: только иногда.
Странно, что и с этими опциями случается. Или Вы используете
SO_REUSEADDR ? Hадежнее SO_REUSEPORT. Хотя, при ТОЛЬКО CLOSE_WAIT
сокетах это играть не должно. Hе знаю, правда, насчет solaris.
Да, а что - "оно" ? EADDRINUSE ? Или CLOSE_WAIT ?
Кстати, еще один аргумент в пользу висячих потомков. К тому же, не
может ли случиться такое, что потомок-таки тоже порт слушать пытается
или просто забинженый держит ? Тогда бы объяснилось EADDRINUSE при
CLOSE_WAIT и SO_REUSEADDR.
--
Anatoly A. Orehovsky. AO9-RIPE. AAO1-RIPN
http://www.tekmetrics.com/transcript.shtml?pid=6064
--- ifmail v.2.14dev3
* Origin: CISA Ltd. InterNetNews site (2:5020/400)
827 Прочтений • [как избежать CLOSE_WAIT (socket)] [08.05.2012] [Комментариев: 0]