boost::asio::streambuf::consume - Injects garbage character
Asked Answered
R

1

3

When I lose connection, in my server code, I try to reconnect in a loop forever. Once I reconnect, I send a login message to the component I am connected to. That component then sends back a login response that looks like "MyResponse"

The initial connection works fine. After I reconnect, however, I get garbage before the expected message, that looks like: "ýMyResponse"

After googling this. I see many questions on Stack Overflow about the boost::asio::streambuf that is used for async sockets in boost::asio. Particularly about reusing he buffer. I have followed the advice there and called consume upon disconnecting. In other words, I call boost::asio::streambuf::consume after I call shutdown and close on my socket, after being called back with an error on recv in response to a call to recv_until.

I have also used wireshark to make sure that the garbage character is not being sent and it is not.

After much debugging, it appears as though the calls to consume are injecting a character rather than clearing out all characters.

Here is a minimal example:

#include <boost/asio.hpp>

#include <iostream>
#include <sstream>
#include <string>

int main()
{
    boost::asio::streambuf buffer;

    std::cout << "buffer size " << buffer.size() << std::endl;

    buffer.consume(std::numeric_limits<size_t>::max());

    std::cout << "buffer size " << buffer.size() << std::endl;

    std::istream is(&buffer);
    std::string contents;
    is >> contents;

    std::cout << "Contents: "  << contents << std::endl;

    std::cout << "buffer size " << buffer.size() << std::endl;

    return 0;
}

Output:

buffer size 0
buffer size 1
Contents: ²
buffer size 0

Expected Output:

buffer size 0
buffer size 0
Contents:
buffer size 0

If I do not use consume, I get some of the message, previous to disconnect, before the first message after reconnection, in my server code.

If I do use consume, I get a garbage character.

See:

Working with boost::asio::streambuf

Read until a string delimiter in boost::asio::streambuf

boost asio async_read: the read message adds to itself

Rossman answered 27/10, 2017 at 17:56 Comment(6)
@Justin, according to the boost documentaion and what I gleamed from the posted links, a call to consume should clear the input sequence. It should not result in additional characters. I am trying to clear any left over data from recv calls on my socket prior to reusing the buffers in recv calls after a reconnection. Edited the post with the addtional info.Rossman
When I look at this question now, I think this is a good question and that it has a minimal reproducible example. I don't know how to solve your problem, but I think that this is a good question. Good jobDisgust
As for why this question was probably downvoted in the beginning, you had a massive amount of code posted here. That is certainly not minimal, and it wasn't complete, so people downvoted as such.Disgust
Which version of boost are you using?Santee
A cursory glance at the implementation suggest that there is an overflow problem (max std::size_t to int results in -1), that is then passed to gbump() with no bound checks that may result in undefined behavior. I can investigate in more detail later, but in the meantime, to consume the entire streambuf, consider explicitly passing streambuf::size() to streambuf::consume().Melisa
@Tanner my debugging seems to agree. I've tried streambuf::max_size() with same result, but if I plug in something smaller, like 2048, then I get the expected results. Can someone report this to the boost mailing list? I am denied access at work. I will change to a smaller size for now, like streambuf::size() as you suggested. Thanks Tanner.Rossman
R
2

boost::asio::streambuf::consume overflows.

Use

buffer.consume(buffer.size());

Rather than

buffer.consume(std::numeric_limits<size_t>::max());

Reporting bug to boost mailing list.

Rossman answered 30/10, 2017 at 14:53 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.