Boost.Asio: операция отменена на async_read
Еще один в продолжающейся саге о себе против Boost.Asio...
У меня есть простой асинхронный клиент и сервер, которые используют async_write и async_read для связи. Клиент может успешно записывать байты в сокет, но сервер их никогда не видит; мой обработчик чтения на сервере не работает с "Операцией отменена".
Я склонен полагать, что это может быть проблема с синхронизацией с клиентом, который записывает данные после того, как сервер попытался прочитать его и потерпел неудачу, но я бы подумал, что данные все равно будут ждать в соке (если только сокет был закрыт тем временем).
Чтобы проверить это, я просто перезапустил операцию чтения в обработчике ошибок, то есть
read_handler()
{
if (!error) {
/* bytes read */
} else {
async_read(socket, buffer, read_handler)
}
}
Но все это привело меня к segfault в pthread_mutex_lock
через вызов async_receive
.
Может ли кто-нибудь указать мне в сторону какой-либо релевантной информации (или, еще лучше, сказать мне, что я делаю неправильно?))?
UPDATE. Сервер и клиент основаны на примере сервера чата в документах Asio, при этом клиент и сервер работают под одним и тем же процессом (может быть, это проблема? они оба используют один и тот же io_service...); как асинхронный, так и с использованием Boost 1.44.0. Я работаю над OS X, но это также воспроизводится на Linux.
ОБНОВЛЕНИЕ II. Моя догадка была правильной, и если серверу и клиенту предоставлены отдельные объекты io_service, async_read видит байты в сокете. Это все равно дает segfault в boost::asio::detail::kqueue_reactor::post_immediate_completion
, который, как представляется, связан с io_service.run()
. Прежде чем идти дальше, использует отдельный объект io_service
правильный подход?
Ответы
Ответ 1
Операция отменена (код ошибки operation_aborted) отправляется, когда сокет закрыт или отменен.
Скорее всего, ваше соединение каким-то образом выходит из сферы действия.
Возможно, как это случилось со мной, вы забыли присоединить async_handlers к указателю shared_from_this().
То есть Вы должны подключить своих обработчиков следующим образом:
async_read(m_socket,
boost::asio::buffer((void*)m_buffer, m_header_size),
boost::bind(&TcpConnection::handleRead,
shared_from_this(),
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
И НЕ:
async_read(m_socket,
boost::asio::buffer((void*)m_buffer, m_header_size),
boost::bind(&TcpConnection::handleRead,
this, //<- This will go out of scope and the socket will be closed
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));