Modify

Ticket #8722 (closed Bugs: fixed)

Opened 10 months ago

Last modified 7 months ago

The boost::asio::windows::stream_handle::read_some method may (incorrectly) throw when used with named-pipes in message mode (on Windows) and receives an ERROR_MORE_DATA error

Reported by: Dentcho Bankov <dbankov@…> Owned by: chris_kohlhoff
Milestone: To Be Determined Component: asio
Version: Boost Development Trunk Severity: Problem
Keywords: Cc: chris_kohlhoff

Description

Please note that this ticket is similar to Ticket#2936.

When using named-pipes in message mode on Windows it is possible that the read operation on the client side will fail with GetLastError?() == ERROR_MORE_DATA. In the overlapped IO case the latter means that GetOverlappedResult?(...) fails and reports this error.

Now looking at the win_iocp_handle_service::do_read(...) when in the above scenario if the GetOverlappedResult?(...) fails do_read(...) would update the ec parameter with the error value (in this case ERROR_MORE_DATA) and then boost::asio::windows::stream_handle::read_some(...) would throw. The latter may be incorrect as the ReadFile?(...) function may have actually read some data but the information about this data (bytes read) would be lost when the exception is thrown leaving the upper layers practically unable to recover from this situation even if they'd catch the exception... (see attached code)

It seems the fix for this should be to avoid throwing the exception by adding an "if" statement similar to the one after the ReadFile?(...) call (several lines above in do_read(...)) e.g. making the code around GetOverlappedResult?(...) look as follows:

Wait for the operation to complete. DWORD bytes_transferred = 0; ok = ::GetOverlappedResult?(impl.handle_,

&overlapped, &bytes_transferred, TRUE);

if (!ok) {

DWORD last_error = ::GetLastError?(); if (last_error != ERROR_MORE_DATA) <---- added "if" statement {

if (last_error == ERROR_HANDLE_EOF) {

ec = boost::asio::error::eof;

} else {

ec = boost::system::error_code(last_error,

boost::asio::error::get_system_category());

} return 0;

}

}

Please comment if the proposed fix is correct as I'd like to apply it before it is released in an official BOOST release.

Attachments

BOOSTCA.7z Download (1.2 KB) - added by Dentcho Bankov <dbankov@…> 10 months ago.
Windows named-pipe message mode example illustrating the described problem
proposedFix.patch Download (1004 bytes) - added by Dentcho Bankov <dbankov@…> 10 months ago.
Proposed fix patch

Change History

Changed 10 months ago by Dentcho Bankov <dbankov@…>

Windows named-pipe message mode example illustrating the described problem

Changed 10 months ago by Dentcho Bankov <dbankov@…>

Proposed fix patch

comment:1 Changed 10 months ago by Dentcho Bankov <dbankov@…>

Code formatting in my previous comment is awful. I'm sorry I should have previewed it.

Here is another attempt:

// Wait for the operation to complete.
DWORD bytes_transferred = 0;
ok = ::GetOverlappedResult(impl.handle_,
    &overlapped, &bytes_transferred, TRUE);
if (!ok)
{
  DWORD last_error = ::GetLastError();
  if (last_error != ERROR_MORE_DATA) // <--- the added "if" statement
  {
    if (last_error == ERROR_HANDLE_EOF)
    {
      ec = boost::asio::error::eof;
    }
    else
    {
      ec = boost::system::error_code(last_error,
           boost::asio::error::get_system_category());
    }
    return 0;
  }
}

comment:2 Changed 7 months ago by chris_kohlhoff

  • Status changed from new to closed
  • Resolution set to fixed

Fixed on trunk in [85759]. Merged to release in [85838].

View

Add a comment

Modify Ticket

Change Properties
<Author field>
Action
as closed
The resolution will be deleted. Next status will be 'reopened'
Author


E-mail address and user name can be saved in the Preferences.

 
Note: See TracTickets for help on using tickets.