windows: call CancelIo when canceling an fs watch

This commit is contained in:
Andrew Kelley 2018-08-10 13:19:07 -04:00
parent 0df485d4dc
commit 598e80957e
5 changed files with 18 additions and 10 deletions

View File

@ -545,14 +545,15 @@ pub const Compilation = struct {
try comp.initTypes();
defer comp.primitive_type_table.deinit();
comp.main_loop_handle = async comp.mainLoop() catch unreachable;
// Set this to indicate that initialization completed successfully.
// from here on out we must not return an error.
// This must occur before the first suspend/await.
comp.main_loop_handle = async comp.mainLoop() catch unreachable;
out_comp.* = ∁
// This suspend is resumed by destroy()
suspend;
// From here on is cleanup.
await (async comp.deinit_group.wait() catch unreachable);
if (comp.tmp_dir.getOrNull()) |tmp_dir_result| if (tmp_dir_result.*) |tmp_dir| {

View File

@ -43,7 +43,7 @@ pub const TestContext = struct {
.file_index = std.atomic.Int(usize).init(0),
};
try self.loop.initMultiThreaded(allocator);
try self.loop.initSingleThreaded(allocator);
errdefer self.loop.deinit();
self.zig_compiler = try ZigCompiler.init(&self.loop);

View File

@ -1117,6 +1117,9 @@ pub fn Watch(comptime V: type) type {
// TODO only 1 beginOneEvent for the whole coroutine
self.channel.loop.beginOneEvent();
errdefer self.channel.loop.finishOneEvent();
errdefer {
_ = windows.CancelIoEx(dir_handle, &overlapped);
}
suspend {
_ = windows.ReadDirectoryChangesW(
dir_handle,

View File

@ -686,6 +686,7 @@ pub const Loop = struct {
switch (os.windowsGetQueuedCompletionStatus(self.os_data.io_port, &nbytes, &completion_key, &overlapped, windows.INFINITE)) {
os.WindowsWaitResult.Aborted => return,
os.WindowsWaitResult.Normal => {},
os.WindowsWaitResult.Cancelled => continue,
}
if (overlapped != null) break;
}

View File

@ -238,21 +238,24 @@ pub fn windowsPostQueuedCompletionStatus(completion_port: windows.HANDLE, bytes_
}
}
pub const WindowsWaitResult = error{
pub const WindowsWaitResult = enum{
Normal,
Aborted,
Cancelled,
};
pub fn windowsGetQueuedCompletionStatus(completion_port: windows.HANDLE, bytes_transferred_count: *windows.DWORD, lpCompletionKey: *usize, lpOverlapped: *?*windows.OVERLAPPED, dwMilliseconds: windows.DWORD) WindowsWaitResult {
if (windows.GetQueuedCompletionStatus(completion_port, bytes_transferred_count, lpCompletionKey, lpOverlapped, dwMilliseconds) == windows.FALSE) {
if (std.debug.runtime_safety) {
const err = windows.GetLastError();
if (err != windows.ERROR.ABANDONED_WAIT_0) {
std.debug.warn("err: {}\n", err);
const err = windows.GetLastError();
switch (err) {
windows.ERROR.ABANDONED_WAIT_0 => return WindowsWaitResult.Aborted,
windows.ERROR.OPERATION_ABORTED => return WindowsWaitResult.Cancelled,
else => {
if (std.debug.runtime_safety) {
std.debug.panic("unexpected error: {}\n", err);
}
}
assert(err == windows.ERROR.ABANDONED_WAIT_0);
}
return WindowsWaitResult.Aborted;
}
return WindowsWaitResult.Normal;
}