I have a client which connects to a named pipe as follows:
CreateFile(pipeName.c_str(),GENERIC_READ | GENERIC_WRITE, 0, nullptr, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, nullptr);
The result of this call is assigned to a stream_handle. I want that io service shuts down orderly by run() returning due to running out of work. To achieve this, I post a lambda that effectively calls cancel() on the handle (hidden inside Kill()):
_io.post([this]() {
for (auto& w : _workers) w->Kill();
});
However, cancel() has no effect: the callback for async_read continues to return with error code of zero and data read from the pipe. For reference, this is the read call with its handler:
ReadCompleted() processes the received data and loops by calling read() again.
If I call close() the callback gets an error code and everything works out correctly, *except* that I get an error code [invalid handle] that gets logged as an error (though it's not).
Am I correct in assuming that cancel() is an apparent noop in this case because of the race-condition where an I/O request completes successfully before cancel is invoked?
If so, can you suggest a more elegant way (i.e., a way that doesn't induce a hard error) of exiting a loop as described here? Setting a member variable instead of calling cancel?
Given the existence of the race-condition, what are use-cases for cancel? How to use it correctly, if at all possible?
-- Stian