zxctatar
zxctatar

Reputation: 135

(process 7352) terminated with the code -1073741819

I am trying to make a REASON API server that will accept requests from another application, but the problem is that after the first connection to it, it shuts down with the error -1073741819. When I went through it with the debugger, I found out that the error is called buffer_ "An unhandled exception was caused: a violation of read access.this was 0xffffffffffffffffff.", but I do not know how to solve this problem

cpp.file
-------------------
#include "Server.h"

using namespace boost::asio;
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, boost::asio::ip::tcp::endpoint(boost::asio::ip::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) {
                ProcessRequest();
            }
            else {
                std::cerr << "Error ReadRequest: " << ec.message() << std::endl;
            }
        });
}

void 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();
        
        WriteResponse(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() = "Invalide request!";
        response.prepare_payload();
        
        WriteResponse(response);
    }
}

void Server::WriteResponse(boost::beast::http::response<boost::beast::http::string_body>& response_){
    http::async_write(socket_, response_,
        [this](boost::system::error_code ec, size_t byte) {
            if (ec) {
                std::cerr << "Error WriteResponse: " << ec.message() << std::endl;
            }
            StartAccept();
        });
}
h.file
---------------
#include <iostream>
#include <boost/asio.hpp>
#include <boost/beast.hpp>
#include <string>

class Server {
public:
    Server(boost::asio::io_service& io_service, int port);

private:
    void StartAccept(); 
    void ReadRequest(); 
    void ProcessRequest(); 
    void WriteResponse(boost::beast::http::response <boost::beast::http::string_body>& response_); 

    boost::asio::ip::tcp::acceptor acceptor_; 
    boost::asio::ip::tcp::socket socket_; 
    boost::beast::flat_buffer buffer_; 
    boost::beast::http::request<boost::beast::http::string_body> request_; 
};

Upvotes: -1

Views: 90

Answers (1)

sehe
sehe

Reputation: 393769

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();
     }
    

Upvotes: 0

Related Questions