boostorg/beast

boost::beast::http::async_read core dumped when reading chunked response

xiaoma565 opened this issue · 4 comments

in class ClientConnection
image
It has a variable "boost::beast::http::parser<false, boost::beast::http::empty_body> p_"

ClientConnection function "Start" call ClientConnection function "DoReadHeader"

image

In function "OnReadHeader"
I call "on_chunk_header" and "on_chunk_body"
image
image

And then running "boost::beast::http::async_read"
image

function "ParserChunkHeader" seem like
image

function "ParserChunkBody"
image

in "OnChunkBody", when p_ is done, close the socket, else keep reading
image

when I run the program
image

run in gdb
image

http::parser::on_chunk_header stores a reference to the provided callback object. Therefore, you need to extend the lifetime of the headerCB and bodyCB variables by making them members of your class.

The reason for storing references is that most std::function implementations utilize small buffer optimization, meaning storing a reference won't require a memory allocation. A better alternative would be to accept std::function_ref, but that's a C++26 feature.

http::parser::on_chunk_header stores a reference to the provided callback object. Therefore, you need to extend the lifetime of the headerCB and bodyCB variables by making them members of your class.

The reason for storing references is that most std::function implementations utilize small buffer optimization, meaning storing a reference won't require a memory allocation. A better alternative would be to accept std::function_ref, but that's a C++26 feature.

thanks so much! It is helpful. But I have got another problem.
In my http server, I read a request and send some chunked messages. When I send the last chunk

boost::asio::async_write(stream_, http::make_chunk_last(), [this](boost::system::error_code ec, std::size_t bytes_transferred) {
    do_read();
});

I call do_read to read a new reuqest.

void do_read()
{
        req_ = {};

        // Set the timeout.
        stream_.expires_after(std::chrono::seconds(30));

        // Read a request
        http::async_read(stream_, buffer_, req_,
            beast::bind_front_handler(
                &session::on_read,
                shared_from_this()));
}

void on_read(beast::error_code ec, std::size_t bytes_transferred)
{
        boost::ignore_unused(bytes_transferred);

        // This means they closed the connection
        if(ec == http::error::end_of_stream)
            return do_close();

        if(ec)
            return fail(ec, "read");
        handle_request(*doc_root_, std::move(req_));
        send_chunked();
}

I did it with reference to this example: https://www.boost.org/doc/libs/1_85_0/libs/beast/example/http/server/async/http_server_async.cpp

But I got an error: free(): double free detected in tcache 2

boost::asio::async_write(stream_, http::make_chunk_last(), [this](boost::system::error_code ec, std::size_t bytes_transferred) {
    do_read();
});

Here, you capture the this pointer instead of a shared pointer to your object. You are probably facing a lifetime issue as a result.

boost::asio::async_write(stream_, http::make_chunk_last(), [this](boost::system::error_code ec, std::size_t bytes_transferred) {
    do_read();
});

Here, you capture the this pointer instead of a shared pointer to your object. You are probably facing a lifetime issue as a result.

thanks bro!