Subject: [Boost-bugs] [Boost C++ Libraries] #7198: win_iocp_io_service::shutdown_service() wrongly calls win_iocp_operation::destroy() sometimes
From: Boost C++ Libraries (noreply_at_[hidden])
Date: 2012-08-06 13:41:39
#7198: win_iocp_io_service::shutdown_service() wrongly calls
win_iocp_operation::destroy() sometimes
-------------------------------------------------------+--------------------
Reporter: Peter Jakubco <peter.jakubco@â¦> | Type: Bugs
Status: new | Milestone: To Be Determined
Component: None | Version: Boost 1.51.0
Severity: Problem | Keywords:
-------------------------------------------------------+--------------------
I use Windows pipe connection between two windows processes (service and a
process). When service creates the process, it immediately creates pipe
connection with the process and sends some commands to it. The process,
immediately after start, tries to connect to that pipe.
For the asynchronous communication I use `boost::asio::io_service` and
`boost::asio::windows::stream_handle` (for both processes), using the
`io_service` and windows handle of the pipe (obtained via
`::CreateNamedPipeA` WinAPI).
For writing the message from the service to the process, I use a call of:
{{{
boost::asio::async_write(windows_stream_handle, boost::asio::buffer(msg),
h);
}}}
The problem is when the process exits (end up) during pending IO operation
and the `io_service` object is deleted during that operation (because
process has exited and the service is no longer needed), `AccessViolation`
exception raises causing crash of the service.
I have debugged my code using WinDbg and it points into the boost code.
The WinDbg image can be found here: http: //2i.cz/bef22f05d6
I have looked into the boost code, and I think I found the problem. Inside
file `boost/asio/detail/impl/win_iocp_io_service.ipp`, method `void
win_iocp_io_service::shutdown_service()` contains the following code:
{{{
void win_iocp_io_service::shutdown_service()
{
...
::GetQueuedCompletionStatus(iocp_.handle, &bytes_transferred,
&completion_key, &overlapped, gqcs_timeout);
if (overlapped) // bytes_transferred > 0 ??
{
::InterlockedDecrement(&outstanding_work_);
static_cast<win_iocp_operation*>(overlapped)->destroy();
}
...
}
}}}
According to MSDN, function `GetQueuedCompletionStatus` returns `TRUE` if
the operation succeedes, and `FALSE` if not. See the link: http:
//msdn.microsoft.com/en-us/library/windows/desktop/aa364986(v=vs.85).aspx
After quick fix:
{{{
BOOL result = ::GetQueuedCompletionStatus(iocp_.handle,
&bytes_transferred, &completion_key, &overlapped, gqcs_timeout);
if (result && overlapped) // bytes_transferred > 0 ??
{
::InterlockedDecrement(&outstanding_work_);
static_cast<win_iocp_operation*>(overlapped)->destroy();
}
}}}
it works well. PLease, have a look on it. Thanks.
-- Ticket URL: <https://svn.boost.org/trac/boost/ticket/7198> Boost C++ Libraries <http://www.boost.org/> Boost provides free peer-reviewed portable C++ source libraries.
This archive was generated by hypermail 2.1.7 : 2017-02-16 18:50:10 UTC