Commit 598e80957e

Andrew Kelley <superjoe30@gmail.com>
2018-08-10 19:19:07
windows: call CancelIo when canceling an fs watch
1 parent 0df485d
Changed files (5)
src-self-hosted
std
event
os
windows
src-self-hosted/compilation.zig
@@ -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.* = &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| {
src-self-hosted/test.zig
@@ -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);
std/event/fs.zig
@@ -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,
std/event/loop.zig
@@ -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;
                     }
std/os/windows/util.zig
@@ -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;
 }