Разблокировка принять () - PullRequest
       2

Разблокировка принять ()

1 голос
/ 10 сентября 2010

У меня есть блокирующий вызов, чтобы принять (). Из другого потока я закрываю сокет, надеясь, что он разблокирует вызов accept (), что и происходит, но у меня есть случай, когда он этого не делает, например: поток A входит в accept (), поток B закрывает сокет, поток A не возвращается из accept ().

Вопрос: что может привести к закрытию сокета, чтобы не разблокировать accept ()?

Ответы [ 3 ]

2 голосов
/ 23 мая 2013

Один хакерский трюк, чтобы разблокировать accept(2) - это на самом деле connect(2) к концу прослушивания из вашего другого потока. Установите флажок, указывающий, что пора остановить цикл, connect(2), close(2) соединительный разъем. Таким образом, поток accept(2) будет знать, что закрыть сокет и отключиться.

1 голос
/ 17 сентября 2011

Вы никогда не должны освобождать ресурс в одном потоке, когда другой поток использует или может использовать его. Вы никогда не получите надежную работу. С одной стороны, вы никогда не можете быть на 100% уверены, что поток действительно заблокирован в accept, в отличие от того, что собирается блокировать его. Так что всегда будут условия гонки.

И, конечно, shutdown не будет работать, потому что сокет не подключен.

Есть несколько способов справиться с этой проблемой. Например, вы можете установить флаг, который поток проверяет при возврате из accept, а затем установить соединение самостоятельно. Это приведет к тому, что поток вернется из accept, а затем увидит флаг и завершится.

Вы также можете переключиться на неблокирующие розетки. Пусть поток вызовет select или poll с таймаутом и проверит, должен ли поток завершиться при возврате из select или poll. Вы также можете select или poll как на сокете, так и на трубе. Затем просто отправьте байт на канал, чтобы разблокировать поток. pthread_kill это еще одна возможность, как pthread_cancel.

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

0 голосов
/ 10 сентября 2010

Попробуйте позвонить shutdown(), а затем close() из потока B . Вы также должны проверять коды возврата для этих вызовов, поскольку они могут помочь вам выяснить, что происходит не так, как поток A не может разблокироваться.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...