[Boost-bugs] [Boost C++ Libraries] #7198: win_iocp_io_service::shutdown_service() wrongly calls win_iocp_operation::destroy() sometimes

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