From f5c609965628d2ce8fb815935168bd1800a3c652 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B6nke=20Ludwig?= Date: Fri, 18 Sep 2020 10:00:30 +0200 Subject: [PATCH] Work around critical issue in eventcore's cancelRead/cancelWrite. The file I/O versions of cancelRead and cancelWrite in eventcore currently do not reliably cancel the operation in a synchronous fashion, leading to continued buffer accesses after the cancellation call. In case of the Windows version, this also means that the OVERLAPPED structure can be illegally reused for the next operation, while the previous one hasn't been canceled, yet. A solution to this issue may require a fundamental change in the file I/O API of eventcore, and the optimal design of that still needs to be worked out. For this reason, we simply avoid using the cancellation functions in vibe-core for now to avoid memory corruption issues. This does mean that interrupting a task that does file I/O won't work anymore. --- source/vibe/core/file.d | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/source/vibe/core/file.d b/source/vibe/core/file.d index bce1f93..d537127 100644 --- a/source/vibe/core/file.d +++ b/source/vibe/core/file.d @@ -607,9 +607,11 @@ struct FileStream { size_t read(ubyte[] dst, IOMode mode) { - auto res = asyncAwait!(FileIOCallback, - cb => eventDriver.files.read(m_fd, ctx.ptr, dst, mode, cb), - cb => eventDriver.files.cancelRead(m_fd) + // NOTE: cancelRead is currently not behaving as specified and cannot + // be relied upon. For this reason, we MUST use the uninterruptible + // version of asyncAwait here! + auto res = asyncAwaitUninterruptible!(FileIOCallback, + cb => eventDriver.files.read(m_fd, ctx.ptr, dst, mode, cb) ); ctx.ptr += res[2]; enforce(res[1] == IOStatus.ok, "Failed to read data from disk."); @@ -624,9 +626,11 @@ struct FileStream { size_t write(in ubyte[] bytes, IOMode mode) { - auto res = asyncAwait!(FileIOCallback, - cb => eventDriver.files.write(m_fd, ctx.ptr, bytes, mode, cb), - cb => eventDriver.files.cancelWrite(m_fd) + // NOTE: cancelWrite is currently not behaving as specified and cannot + // be relied upon. For this reason, we MUST use the uninterruptible + // version of asyncAwait here! + auto res = asyncAwaitUninterruptible!(FileIOCallback, + cb => eventDriver.files.write(m_fd, ctx.ptr, bytes, mode, cb) ); ctx.ptr += res[2]; if (ctx.ptr > ctx.size) ctx.size = ctx.ptr;