LINUX.ORG.RU

[Haskell][TCP сервер]Чтение из закрытого сокета/хендла

 


0

0

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

Чтобы воспроизвести проблему я запускаю сервер, захожу неткатом на него, отсылаю строки [«QUIT», «1», «2»] и пустую строку, завершающую пакет. Сервер реагирует на это отключением клиента с сообщением [«BYE», «1»]. Далее запускаю некат и повторяю действия, и тут начинаются «чудеса». Поясню, как работает сервер: на каждого клиента заводятся потоки (forkIO) на приём и на отправку, общающиеся с основным потоком через Chan-ы. Таким образом, на приём работает что-то вида

forever (hGetLine handle >>= \msg -> writeChan chan $ Message (clientId, msg))
Поток висит на hGetLine, и при получении строки отсылает её ядру сервера. При отключении клиента по идее он должен просто отваливаться с исключением.

Но тут случается странная вещь. Когда сервер отключает первое подключение, слушающий поток продолжает ждать строку от хендла. При повторном подключении система выдаёт хендл с тем же номером, создаётся второй поток, и теперь два потока ждут строки! Более того, они оба получают эти строки, каждый через одну. Соответственно, первый поток присылает ядру команды от уже несуществующего клиента, второй поток присылает неправильные команды от текущего клиента. Переписывание сетевой части с хендлов на сокеты ситуацию никак не изменило.

Вопросов куча. Почему при закрытии хендла/сокета могут оставаться потоки, ждущие с него данных, и более того, продолжающие читать с нового хендла/сокета с тем же номером? Как бороться с таким поведением? Как вообще правильно писать такие программы на хаскеле? Как работают с блокирующими вызовами в программах на других ЯП? Почему раньше работало, а сейчас перестало?

★★★★★
Ответ на: комментарий от exlevan

Вообще, речь идёт о сервере hedgewars (http://fireforge.net/scm/?group_id=11), из тега 0.9.12 (в транке поломан). Пытался отделить только нужное - получается довольно много кода. Пробовал разные версии компилятора ghc: 6.10.3 и 6.12.2

unC0Rr ★★★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.