LINUX.ORG.RU

Как прервать бустовый asio acceptor::accept() из другого потока?

 ,


0

2

Пытаюсь немного освоить Boost.Asio, и при написании серверной части возник вопрос. Вот допустим у меня отдельный рабочий поток и в нём в цикле крутится tcp::acceptor::accept(…), вопрос, как мне из другого потока прервать ожидание на вызове accept(), что бы завершить работу цикла?

★★★

хз как оно там в бусте, но из общих соображений

  • close() сокета из любого другого потока приведет к возникновению exception в потоке, который висит в accept()
  • установить опцию таймаута на сокет и по таймауту проверять состояние некоторой переменной, типа (псевдокод)
while(true){
    try{
        ... accept();
        ...
    }catch(SocketTimeoutException e){
        if(stopped) break;
       ...
    }
}
graceful_shutdown();
olelookoe ★★★
()

Тоже недавно искал ответ, ничего внятного не попалось. Решил, в итоге, по-индусски: из второго потока сделал коннект, а первый там уже по заранее установленному флагу вышел. Сеньор на ревью молча пропустил, видимо, такое приемлемо. Правда, и проект был не боевой, а так, на выброс.

JaneDoe
()

Если в блокирующем режиме, то по нормальному никак. Если не по нормальному, то каждый поток это процесс со своим pid, просто прибей его, главное убедиться что этот цель не родитель, или же сделать detach отцепить сперва потомка от родителя

sparks ★★★★
()
Последнее исправление: sparks (всего исправлений: 1)

Про Boost.Asio не знаю.

Я бы попробовал воспользоваться «man siginterrupt»

Разрешить его для какого-нибудь сигнала типа USR2 и этим сигналом прерывать.

На выходе из syscall ты получишь errno EINTR

vel ★★★★★
()

close() сокета из любого другого потока приведет к возникновению exception в потоке, который висит в accept()

Вот это вот именно то чего Вы хотите. А если спим не в accept(), а в select()/epoll() - to eventfd в помощь.

bugfixer ★★★★★
()
Последнее исправление: bugfixer (всего исправлений: 1)

Блин, нафига вы в многопоточку лезете не разобравшись в асинхронке?)

В общем случаи синхронную операцию accept прервать нельзя, закрывать сокет/аццпетор из другого потока лютый костыть.

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

boost::asio::any_io_executor executor = listener.get_executor();
boost::asio::post(executor,
                  [&listener]() { listener.cancel(); });

В этом случаи обращения к аццетору будут производиться только из одного треда и соответственно конкурировать не будут (в одном треде они только по очереди могут быть). Если для метода объекта явно не указано thread safe, то обращаться к нему из параллельного треда не нужно, это плохая затея.

dvetutnev
()
Последнее исправление: dvetutnev (всего исправлений: 2)
Ответ на: комментарий от dvetutnev

Блин, нафига вы в многопоточку лезете не разобравшись в асинхронке?)

Что-то не приметил разбросанных на каждом углу методичек о том, в какой правильной с асинхронкой последовательности лезть в многопоточку. Просто подошёл с того краю, который был ближе, в каждом туторе показывают синхронную схему, что я должен был подумать?

normann ★★★
() автор топика
Ответ на: комментарий от normann

вопрос, как мне из другого потока прервать ожидание на вызове accept(), что бы завершить работу цикла?

Если ты хочешь прервать ожидание на вызове accept() из другого потока, и всё это в рамках Boost::ASIO, то я ничего не перепутал.

Но спорить с тобой я не буду. Делай что хочешь.

pathfinder ★★★★
()
Последнее исправление: pathfinder (всего исправлений: 1)
Ответ на: комментарий от pathfinder

Ты уже с кем-то споришь, только с кем, не понятно, при этом ни слова полезного в ветке по теме не сказал, только нафлудил. Ты предъявил мне буд-то я что-то «хочу», но не привёл, где я говорю, что я этого «хочу». Не читал, но осуждаю, да? Это за такие разговоры у тебя четыре звезды?

normann ★★★
() автор топика