beast icon indicating copy to clipboard operation
beast copied to clipboard

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

Open xiaoma565 opened this issue 1 year ago • 2 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

xiaoma565 avatar May 25 '24 03:05 xiaoma565

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.

ashtum avatar May 25 '24 05:05 ashtum

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

xiaoma565 avatar May 25 '24 08:05 xiaoma565

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.

ashtum avatar May 25 '24 12:05 ashtum

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!

xiaoma565 avatar May 25 '24 13:05 xiaoma565