Properly increment waiter count for WinAPI file I/O operations.

This commit is contained in:
Sönke Ludwig 2017-11-25 16:47:29 +01:00
parent 2e3f145f0f
commit 2d4ccf454d
2 changed files with 15 additions and 2 deletions

View file

@ -36,7 +36,11 @@ final class WinAPIEventDriverCore : EventDriverCore {
override size_t waiterCount() { return m_waiterCount + m_timers.pendingCount; } override size_t waiterCount() { return m_waiterCount + m_timers.pendingCount; }
package void addWaiter() { m_waiterCount++; } package void addWaiter() { m_waiterCount++; }
package void removeWaiter() { m_waiterCount--; } package void removeWaiter()
{
assert(m_waiterCount > 0, "Decrementing waiter count below zero.");
m_waiterCount--;
}
override ExitReason processEvents(Duration timeout = Duration.max) override ExitReason processEvents(Duration timeout = Duration.max)
{ {
@ -216,6 +220,7 @@ private struct HandleSlot {
package struct FileSlot { package struct FileSlot {
static struct Direction(bool RO) { static struct Direction(bool RO) {
OVERLAPPED overlapped; OVERLAPPED overlapped;
WinAPIEventDriverCore core;
FileIOCallback callback; FileIOCallback callback;
ulong offset; ulong offset;
size_t bytesTransferred; size_t bytesTransferred;

View file

@ -96,7 +96,9 @@ final class WinAPIEventDriverFiles : EventDriverFiles {
slot.offset = offset; slot.offset = offset;
slot.buffer = buffer; slot.buffer = buffer;
slot.mode = mode; slot.mode = mode;
slot.core = m_core;
slot.callback = on_write_finish; slot.callback = on_write_finish;
m_core.addWaiter();
startIO!(WriteFileEx, true)(h, slot); startIO!(WriteFileEx, true)(h, slot);
} }
@ -113,7 +115,9 @@ final class WinAPIEventDriverFiles : EventDriverFiles {
slot.offset = offset; slot.offset = offset;
slot.buffer = buffer; slot.buffer = buffer;
slot.mode = mode; slot.mode = mode;
slot.core = m_core;
slot.callback = on_read_finish; slot.callback = on_read_finish;
m_core.addWaiter();
startIO!(ReadFileEx, false)(h, slot); startIO!(ReadFileEx, false)(h, slot);
} }
@ -157,13 +161,15 @@ final class WinAPIEventDriverFiles : EventDriverFiles {
auto nbytes = min(slot.buffer.length, DWORD.max); auto nbytes = min(slot.buffer.length, DWORD.max);
if (!() @trusted { return fun(h, &slot.buffer[0], nbytes, &slot.overlapped, &onIOFinished!(fun, RO)); } ()) { if (!() @trusted { return fun(h, &slot.buffer[0], nbytes, &slot.overlapped, &onIOFinished!(fun, RO)); } ()) {
slot.core.removeWaiter();
slot.invokeCallback(IOStatus.error, slot.bytesTransferred); slot.invokeCallback(IOStatus.error, slot.bytesTransferred);
} }
} }
private static void cancelIO(bool RO)(HANDLE h, ref FileSlot.Direction!RO slot) private void cancelIO(bool RO)(HANDLE h, ref FileSlot.Direction!RO slot)
{ {
if (slot.callback) { if (slot.callback) {
m_core.removeWaiter();
//CancelIoEx(h, &slot.overlapped); // FIXME: currently causes linker errors for DMD due to outdated kernel32.lib files //CancelIoEx(h, &slot.overlapped); // FIXME: currently causes linker errors for DMD due to outdated kernel32.lib files
slot.callback = null; slot.callback = null;
slot.buffer = null; slot.buffer = null;
@ -185,6 +191,7 @@ final class WinAPIEventDriverFiles : EventDriverFiles {
} }
if (error != 0) { if (error != 0) {
slot.core.removeWaiter();
slot.invokeCallback(IOStatus.error, slot.bytesTransferred + bytes_transferred); slot.invokeCallback(IOStatus.error, slot.bytesTransferred + bytes_transferred);
return; return;
} }
@ -193,6 +200,7 @@ final class WinAPIEventDriverFiles : EventDriverFiles {
slot.offset += bytes_transferred; slot.offset += bytes_transferred;
if (slot.bytesTransferred >= slot.buffer.length || slot.mode != IOMode.all) { if (slot.bytesTransferred >= slot.buffer.length || slot.mode != IOMode.all) {
slot.core.removeWaiter();
slot.invokeCallback(IOStatus.ok, slot.bytesTransferred); slot.invokeCallback(IOStatus.ok, slot.bytesTransferred);
} else { } else {
startIO!(fun, RO)(h, slot); startIO!(fun, RO)(h, slot);