SIGSEGV при отправке http::response через http::async_write в Boost.Beast
Ловлю SIGSEGV после отправки http::response через http::async_write. Клиент получает ответ, но на сервере до хэндлера http::async_write управление не доходит.
Ответ формируется следующим образом (по примеру из документации):
void func(std::shared_ptr<tcp::socket> socket)
{
http::response<http::string_body> response(http::status::ok, 11);
response.set(http::field::content_type, "json/application");
response.body() = "{}";
response.prepare_payload();
async_write(socket, response);
}
Функция, куда передаётся ответ для последующей отправки:
void async_write(const std::shared_ptr<tcp::socket> &socket, http::response<http::string_body> &response)
{
http::async_write(
*socket,
response,
[this, socket](const system::error_code&, std::size_t)
{
socket->close()
}
);
}
Стэктрейс ошибки:
А строка, где программа прерывается, выглядит так:
template<class Allocator>
inline
boost::asio::const_buffer
basic_fields<Allocator>::
value_type::
buffer() const
{
return boost::asio::const_buffer{
reinterpret_cast<char const*>(this + 1),
static_cast<std::size_t>(off_) + len_ + 2}; // <-
}
Важно отметить, что, если не определять тело ответа, то сигнал не генерируется, однако, хэндлер по прежнему не вызывается.
Ответы (1 шт):
Как уже было отмечено в комментарии, проблема в том, что вы передаете в функцию async_write переменную response по константной ссылке. Так как операция асинхронная, она откладывает свое выполнение, а тем временем программа выходит из функции async_write, а затем и из функции func, в которой был создан объект response. Естественно, при выходе из функции func он разрушается, но не факт, что он успел отправиться асинхронно, в результате чего и получаем ошибку. Для решения проблемы, рекомендую вам создавать в функции func shared_ptr объекта response и передавать его в async_write, а также передать в лямбду по значению, чтобы этот объект не разрушился до вызова лямбды. Вы точно также поступаете с объектом socket. В результате функция async_write будет выглядеть так:
void async_write(std::shared_ptr<tcp::socket> socket, std::shared_ptr<http::response<http::string_body>> response)
{
http::async_write(
*socket,
*response,
[this, socket, response](const system::error_code&, std::size_t)
{
socket->close()
}
);
}
