The error originates in serializing the response.
You can tell by the assert happening in debug mode:
Client connected sotest:
intrusive/detail/hook_traits.hpp:63: static boost::intrusive::bhtraits_b ase<T, NodePtr, Tag, Type>::pointer boost::intrusive::bhtraits_base<T, NodePtr, Tag, Type>::to_value_ptr(node_ptr) [with T = boost::beast::http::basic_fields<std::allocator<char> >::element; NodePtr = boost::intrusive::list_node<v oid*>*; Tag = boost::intrusive::dft_tag; unsigned int Type = 1; pointer = boost::beast::http::basic_fields<std::all ocator<char> >::element*; node_ptr = boost::intrusive::list_node<void*>*]: Assertion '!!p' failed.
gdb tells us the place:
#0 __pthread_kill_implementation (no_tid=0, signo=6, threadid=140737345820608) at ./nptl/pthread_kill.c:44
#1 __pthread_kill_internal (signo=6, threadid=140737345820608) at ./nptl/pthread_kill.c:78
#2 __GI___pthread_kill (threadid=140737345820608, signo=signo@entry=6) at ./nptl/pthread_kill.c:89
#3 0x00007ffff793f476 in __GI_raise (sig=sig@entry=6) at ../sysdeps/posix/raise.c:26
#4 0x00007ffff79257f3 in __GI_abort () at ./stdlib/abort.c:79
#5 0x00007ffff792571b in __assert_fail_base (fmt=0x7ffff7ada130 "%s%s%s:%u: %s%sAssertion `%s' failed.\n%n", assertion=0x555555598094 "!!p", file=0x55555559cd90 "/home/sehe/cu...
#6 0x00007ffff7936e96 in __GI___assert_fail (assertion=0x555555598094 "!!p", file=0x55555559cd90 "/home/sehe/custom/superboost/boost/intrusive/detail/hook_traits.hpp", line=63...
#7 0x0000555555563c11 in boost::intrusive::bhtraits_base<boost::beast::http::basic_fields<std::allocator<char> >::element, boost::intrusive::list_node<void*>*, boost::intrusiv...
#8 boost::intrusive::list_iterator<boost::intrusive::bhtraits<boost::beast::http::basic_fields<std::allocator<char> >::element, boost::intrusive::list_node_traits<void*>, (boo...
#9 boost::intrusive::list_iterator<boost::intrusive::bhtraits<boost::beast::http::basic_fields<std::allocator<char> >::element, boost::intrusive::list_node_traits<void*>, (boo...
#10 boost::beast::http::basic_fields<std::allocator<char> >::writer::field_iterator::operator* (this=0x7fffffffd5c0) at /home/sehe/custom/superboost/boost/beast/http/impl/field...
#11 boost::beast::buffers_cat_view<boost::asio::const_buffer, boost::asio::const_buffer, boost::asio::const_buffer, boost::beast::http::basic_fields<std::allocator<char> >::wri...
#12 0x0000555555590cba in boost::beast::buffers_cat_view<boost::asio::const_buffer, boost::asio::const_buffer, boost::asio::const_buffer, boost::beast::http::basic_fields<std::...
#13 boost::beast::buffers_cat_view<boost::beast::detail::buffers_ref<boost::beast::buffers_cat_view<boost::asio::const_buffer, boost::asio::const_buffer, boost::asio::const_buf...
#14 boost::mp11::detail::mp_with_index_impl_<4ul>::call<0ul, boost::beast::buffers_cat_view<boost::beast::detail::buffers_ref<boost::beast::buffers_cat_view<boost::asio::const_...
#15 boost::mp11::mp_with_index<4ul, boost::beast::buffers_cat_view<boost::beast::detail::buffers_ref<boost::beast::buffers_cat_view<boost::asio::const_buffer, boost::asio::cons...
#16 boost::beast::buffers_cat_view<boost::beast::detail::buffers_ref<boost::beast::buffers_cat_view<boost::asio::const_buffer, boost::asio::const_buffer, boost::asio::const_buf...
#17 boost::beast::buffers_suffix<boost::beast::buffers_cat_view<boost::beast::detail::buffers_ref<boost::beast::buffers_cat_view<boost::asio::const_buffer, boost::asio::const_b...
#18 boost::asio::detail::buffer_size<boost::beast::buffers_suffix<boost::beast::buffers_cat_view<boost::beast::detail::buffers_ref<boost::beast::buffers_cat_view<boost::asio::c...
#19 boost::asio::buffer_size<boost::beast::buffers_suffix<boost::beast::buffers_cat_view<boost::beast::detail::buffers_ref<boost::beast::buffers_cat_view<boost::asio::const_buf...
#20 0x0000555555593cc3 in boost::beast::detail::buffer_bytes_impl::operator()<boost::beast::buffers_suffix<boost::beast::buffers_cat_view<boost::beast::detail::buffers_ref<boos...
#21 boost::beast::http::serializer<false, boost::beast::http::basic_string_body<char, std::char_traits<char>, std::allocator<char> >, boost::beast::http::basic_fields<std::allo...
#22 0x000055555556eec7 in boost::beast::http::detail::write_some_op<boost::beast::http::detail::write_op<boost::beast::http::detail::write_msg_op<Server::WriteResponse(boost::b...
#23 0x000055555556f476 in boost::asio::detail::binder2<boost::beast::http::detail::write_some_op<boost::beast::http::detail::write_op<boost::beast::http::detail::write_msg_op<S...
#24 boost::asio::detail::binder0<boost::asio::detail::binder2<boost::beast::http::detail::write_some_op<boost::beast::http::detail::write_op<boost::beast::http::detail::write_m...
#25 boost::asio::detail::executor_function::complete<boost::asio::detail::binder0<boost::asio::detail::binder2<boost::beast::http::detail::write_some_op<boost::beast::http::det...
#26 0x0000555555585b50 in boost::asio::detail::executor_function::operator() (this=<synthetic pointer>) at /home/sehe/custom/superboost/boost/asio/detail/executor_function.hpp:...
#27 boost::asio::io_context::basic_executor_type<std::allocator<void>, 4ul>::execute<boost::asio::detail::executor_function> (this=0x7fffffffdd70, f=...) at /home/sehe/custom/s...
#28 0x000055555556497a in boost::asio::execution::detail::any_executor_base::execute<boost::asio::detail::binder0<boost::asio::detail::binder2<boost::beast::http::detail::write...
#29 boost::asio::detail::work_dispatcher<boost::asio::detail::binder2<boost::beast::http::detail::write_some_op<boost::beast::http::detail::write_op<boost::beast::http::detail:...
#30 0x0000555555566511 in boost::asio::detail::executor_function::complete<boost::asio::detail::work_dispatcher<boost::asio::detail::binder2<boost::beast::http::detail::write_s...
#31 0x0000555555585a60 in boost::asio::detail::executor_function::operator() (this=<synthetic pointer>) at /home/sehe/custom/superboost/boost/asio/detail/executor_function.hpp:...
#32 boost::asio::detail::executor_op<boost::asio::detail::executor_function, std::allocator<void>, boost::asio::detail::scheduler_operation>::do_complete (owner=0x555555de6000,...
#33 0x00005555555678d7 in boost::asio::detail::scheduler_operation::complete (bytes_transferred=0, ec=..., owner=0x555555de6000, this=0x555555df4000) at /home/sehe/custom/super...
#34 boost::asio::detail::scheduler::do_run_one (ec=..., this_thread=..., lock=..., this=0x555555de6000) at /home/sehe/custom/superboost/boost/asio/detail/impl/scheduler.ipp:493...
#35 boost::asio::detail::scheduler::run (this=0x555555de6000, ec=...) at /home/sehe/custom/superboost/boost/asio/detail/impl/scheduler.ipp:210
#36 0x000055555555fe55 in boost::asio::io_context::run (this=0x7fffffffdf60) at /home/sehe/custom/superboost/boost/asio/impl/io_context.ipp:64
#37 main () at /home/sehe/Projects/stackoverflow/test.cpp:93
The reason is that the response is passed by reference to an async operation. Fix it e.g. by making it a member or using the type-erasing message_generator utility
Showing the latter:
Live On Coliru
#include <boost/asio.hpp>
#include <boost/beast.hpp>
#include <iostream>
#include <string>
class Server {
public:
Server(boost::asio::io_service& io_service, int port);
private:
using Request = boost::beast::http::request<boost::beast::http::string_body>;
using Response = boost::beast::http::message_generator;
void StartAccept();
void ReadRequest();
Response ProcessRequest();
void WriteResponse(Response);
boost::asio::ip::tcp::acceptor acceptor_;
boost::asio::ip::tcp::socket socket_;
boost::beast::flat_buffer buffer_;
Request request_;
};
// #include "Server.h"
namespace beast = boost::beast;
namespace http = beast::http;
using tcp = boost::asio::ip::tcp;
Server::Server(boost::asio::io_service& io_service, int port)
: acceptor_(io_service, tcp::endpoint(tcp::v4(), port))
, socket_(io_service) {
StartAccept();
}
void Server::StartAccept() {
acceptor_.async_accept(socket_, [this](boost::system::error_code ec) {
if (!ec) {
std::cout << "Client connected" << std::endl;
ReadRequest();
} else {
std::cerr << "Client error: " << ec.message() << std::endl;
}
});
}
void Server::ReadRequest() {
buffer_.consume(buffer_.size());
buffer_.prepare(1024);
beast::http::async_read( //
socket_, buffer_, request_, [this](boost::system::error_code ec, size_t /*bytes_transferred*/) {
if (!ec) {
WriteResponse(ProcessRequest());
} else {
std::cerr << "Error ReadRequest: " << ec.message() << std::endl;
}
});
}
Server::Response Server::ProcessRequest() {
if (request_.method() == http::verb::get) {
http::response<http::string_body> response(http::status::ok, request_.version());
response.set(http::field::server, "Boost Beast Server");
response.set(http::field::content_type, "text/plain");
response.keep_alive(request_.keep_alive());
response.body() = "Hello, World";
response.prepare_payload();
return response;
} else {
http::response<http::string_body> response(http::status::bad_request, request_.version());
response.set(http::field::server, "Boost Beast Server");
response.set(http::field::content_type, "text/plain");
response.keep_alive(request_.keep_alive());
response.body() = "Invalid request!";
response.prepare_payload();
return response;
}
}
void Server::WriteResponse(Response res) {
beast::async_write(socket_, std::move(res), [this](boost::system::error_code ec, size_t /*byte*/) {
if (ec) {
std::cerr << "Error WriteResponse: " << ec.message() << std::endl;
}
StartAccept();
});
}
int main() {
boost::asio::io_service ios;
Server s(ios, 8989);
ios.run();
}
The output of test:
g++ -std=c++20 -O2 -Wall -pedantic -pthread main.cpp
./a.out&
sleep 1; curl "http://127.0.0.1:8989/test"
being
Hello, World
I suggest looking at the Beast async http server examples for more good practices!
UPDATE/BONUS
Also showing concurrent connections separating Server from Session and in the process reducing the includes in the header file:
Live On Coliru
File server.h
// server.h
#pragma once
#include <boost/asio/any_io_executor.hpp>
#include <boost/asio/ip/tcp.hpp>
class Server {
public:
Server(boost::asio::any_io_executor ex, uint16_t port);
private:
void StartAccept();
boost::asio::ip::tcp::acceptor acceptor_;
struct Session;
};
File server.cpp
#include "server.h"
#include <boost/asio.hpp>
#include <boost/beast.hpp>
#include <iostream>
namespace beast = boost::beast;
namespace http = beast::http;
using tcp = boost::asio::ip::tcp;
using error_code = beast::error_code;
struct Server::Session : std::enable_shared_from_this<Session> {
Session(tcp::socket s) : socket_(std::move(s)) {}
void Start() { ReadRequest(); }
private:
using Request = http::request<http::string_body>;
using Response = http::message_generator;
void ReadRequest() {
beast::http::async_read( //
socket_, buffer_, request_,
[this, self = shared_from_this()](error_code ec, size_t /*bytes_transferred*/) {
if (!ec) {
WriteResponse(ProcessRequest());
} else {
std::cerr << "Error ReadRequest: " << ec.message() << std::endl;
}
});
}
Response ProcessRequest() {
if (request_.method() == http::verb::get) {
http::response<http::string_body> response(http::status::ok, request_.version());
response.set(http::field::server, "Boost Beast Server");
response.set(http::field::content_type, "text/plain");
response.keep_alive(request_.keep_alive());
response.body() = "Hello, World";
response.prepare_payload();
return response;
} else {
http::response<http::string_body> response(http::status::bad_request, request_.version());
response.set(http::field::server, "Boost Beast Server");
response.set(http::field::content_type, "text/plain");
response.keep_alive(request_.keep_alive());
response.body() = "Invalid request!";
response.prepare_payload();
return response;
}
}
void WriteResponse(Response res) {
beast::async_write(socket_, std::move(res),
[self = shared_from_this()](error_code ec, size_t /*byte*/) {
if (ec) {
std::cerr << "Error WriteResponse: " << ec.message() << std::endl;
}
});
}
tcp::socket socket_;
beast::flat_buffer buffer_;
Request request_;
};
Server::Server(boost::asio::any_io_executor ex, uint16_t port)
: acceptor_(ex, tcp::endpoint(tcp::v4(), port)) {
StartAccept();
}
void Server::StartAccept() {
acceptor_.async_accept([this](error_code ec, tcp::socket s) {
if (!ec) {
std::cout << "Client accepted: " << s.remote_endpoint() << std::endl;
std::make_shared<Session>(std::move(s))->Start();
} else {
std::cerr << "Accept error: " << ec.message() << std::endl;
}
StartAccept();
});
}
int main() {
boost::asio::io_context ioc;
Server s(ioc.get_executor(), 7878);
ioc.run();
}
-1073741819is the same as0xC0000005, which means you have an access violation (buffer overrun) in your program.