Hi –
I believe I’ve identified a potential issue in the Linux code. Say I have a web::http::http_request, and I call set_body(input_stream, content_length, content_type). For some reason (an error case we're testing), although my input stream has 2 MB worth of data, the content_length I pass in is 2MB + 1 (ie longer than the actual buffer length.) On Windows, this works ok – the request gets transmitted to the service, and our service fails the request as expected with a 408. On Linux, Casablanca gets into an infinite recursive loop. The problem seems to be in http_linux.cpp, handle_write_large_body() (line 709). The method is designed to upload client_config().chunksize() bytes at a time. The first line is the check for when the entire buffer has been read:
if (ec || ctx->m_current_size >= ctx->m_known_size)
In this case, after going through the entire buffer, m_current_size is 2 MB, while m_known_size is 2MB + 1. Below that, we have :
const size_t readSize = std::min(client_config().chunksize(), ctx->m_known_size - ctx->m_current_size);
readSize is 1 (m_known_size – m_current_size = (2 MB + 1) – (2 MB) = 1)
readbuf.getn(boost::asio::buffer_cast<uint8_t *>(ctx->m_body_buf.prepare(readSize)), readSize)
.then([=](pplx::task<size_t> op)
{
size_t actualSize = 0;
try
{
actualSize = op.get();
}
actualSize is 0 (because no more bytes could be read from the buffer)
ctx->m_uploaded += (size64_t)actualSize;
ctx->m_current_size += actualSize;
ctx->m_body_buf.commit(actualSize);
None of these values change, and then we recurse forever:
boost::asio::async_write(ctx->m_connection->socket(), ctx->m_body_buf,
boost::bind(&linux_client::handle_write_large_body, shared_from_this(), boost::asio::placeholders::error, ctx));
I don't know if the right answer is to fail or to pass the request through (as in the Windows case), but hanging is probably not what you want to be doing.
-Adam
I believe I’ve identified a potential issue in the Linux code. Say I have a web::http::http_request, and I call set_body(input_stream, content_length, content_type). For some reason (an error case we're testing), although my input stream has 2 MB worth of data, the content_length I pass in is 2MB + 1 (ie longer than the actual buffer length.) On Windows, this works ok – the request gets transmitted to the service, and our service fails the request as expected with a 408. On Linux, Casablanca gets into an infinite recursive loop. The problem seems to be in http_linux.cpp, handle_write_large_body() (line 709). The method is designed to upload client_config().chunksize() bytes at a time. The first line is the check for when the entire buffer has been read:
if (ec || ctx->m_current_size >= ctx->m_known_size)
In this case, after going through the entire buffer, m_current_size is 2 MB, while m_known_size is 2MB + 1. Below that, we have :
const size_t readSize = std::min(client_config().chunksize(), ctx->m_known_size - ctx->m_current_size);
readSize is 1 (m_known_size – m_current_size = (2 MB + 1) – (2 MB) = 1)
readbuf.getn(boost::asio::buffer_cast<uint8_t *>(ctx->m_body_buf.prepare(readSize)), readSize)
.then([=](pplx::task<size_t> op)
{
size_t actualSize = 0;
try
{
actualSize = op.get();
}
actualSize is 0 (because no more bytes could be read from the buffer)
ctx->m_uploaded += (size64_t)actualSize;
ctx->m_current_size += actualSize;
ctx->m_body_buf.commit(actualSize);
None of these values change, and then we recurse forever:
boost::asio::async_write(ctx->m_connection->socket(), ctx->m_body_buf,
boost::bind(&linux_client::handle_write_large_body, shared_from_this(), boost::asio::placeholders::error, ctx));
I don't know if the right answer is to fail or to pass the request through (as in the Windows case), but hanging is probably not what you want to be doing.
-Adam