diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2020-05-02 00:41:19 -0400 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2020-05-02 00:41:19 -0400 |
| commit | 2272a07ca0661547a6889aa7f1b6262fef5dad85 (patch) | |
| tree | c8e093b7c72ac3e1fc2e62931167294941becc7a | |
| parent | 45bce27b8fecda4fba1c22dd191030af29ccbc6f (diff) | |
| download | zig-2272a07ca0661547a6889aa7f1b6262fef5dad85.tar.gz zig-2272a07ca0661547a6889aa7f1b6262fef5dad85.zip | |
std.event.Loop: promote the fs thread to be available for all OS's
| -rw-r--r-- | lib/std/debug.zig | 90 | ||||
| -rw-r--r-- | lib/std/event/loop.zig | 213 | ||||
| -rw-r--r-- | lib/std/fs.zig | 2 | ||||
| -rw-r--r-- | lib/std/os.zig | 19 | ||||
| -rw-r--r-- | lib/std/os/windows.zig | 4 | ||||
| -rw-r--r-- | lib/std/reset_event.zig | 2 |
6 files changed, 137 insertions, 193 deletions
diff --git a/lib/std/debug.zig b/lib/std/debug.zig index 97aa2b6e97..df84a8bbcb 100644 --- a/lib/std/debug.zig +++ b/lib/std/debug.zig @@ -112,39 +112,43 @@ pub fn detectTTYConfig() TTY.Config { /// Tries to print the current stack trace to stderr, unbuffered, and ignores any error returned. /// TODO multithreaded awareness pub fn dumpCurrentStackTrace(start_addr: ?usize) void { - const stderr = getStderrStream(); - if (builtin.strip_debug_info) { - noasync stderr.print("Unable to dump stack trace: debug info stripped\n", .{}) catch return; - return; + noasync { + const stderr = getStderrStream(); + if (builtin.strip_debug_info) { + stderr.print("Unable to dump stack trace: debug info stripped\n", .{}) catch return; + return; + } + const debug_info = getSelfDebugInfo() catch |err| { + stderr.print("Unable to dump stack trace: Unable to open debug info: {}\n", .{@errorName(err)}) catch return; + return; + }; + writeCurrentStackTrace(stderr, debug_info, detectTTYConfig(), start_addr) catch |err| { + stderr.print("Unable to dump stack trace: {}\n", .{@errorName(err)}) catch return; + return; + }; } - const debug_info = getSelfDebugInfo() catch |err| { - noasync stderr.print("Unable to dump stack trace: Unable to open debug info: {}\n", .{@errorName(err)}) catch return; - return; - }; - writeCurrentStackTrace(stderr, debug_info, detectTTYConfig(), start_addr) catch |err| { - noasync stderr.print("Unable to dump stack trace: {}\n", .{@errorName(err)}) catch return; - return; - }; } /// Tries to print the stack trace starting from the supplied base pointer to stderr, /// unbuffered, and ignores any error returned. /// TODO multithreaded awareness pub fn dumpStackTraceFromBase(bp: usize, ip: usize) void { - const stderr = getStderrStream(); - if (builtin.strip_debug_info) { - noasync stderr.print("Unable to dump stack trace: debug info stripped\n", .{}) catch return; - return; - } - const debug_info = getSelfDebugInfo() catch |err| { - noasync stderr.print("Unable to dump stack trace: Unable to open debug info: {}\n", .{@errorName(err)}) catch return; - return; - }; - const tty_config = detectTTYConfig(); - printSourceAtAddress(debug_info, stderr, ip, tty_config) catch return; - var it = StackIterator.init(null, bp); - while (it.next()) |return_address| { - printSourceAtAddress(debug_info, stderr, return_address - 1, tty_config) catch return; + noasync { + const stderr = getStderrStream(); + if (builtin.strip_debug_info) { + stderr.print("Unable to dump stack trace: debug info stripped\n", .{}) catch return; + return; + } + const debug_info = getSelfDebugInfo() catch |err| { + stderr.print("Unable to dump stack trace: Unable to open debug info: {}\n", .{@errorName(err)}) catch return; + return; + }; + const tty_config = detectTTYConfig(); + printSourceAtAddress(debug_info, stderr, ip, tty_config) catch return; + var it = StackIterator.init(null, bp); + while (it.next()) |return_address| { + printSourceAtAddress(debug_info, stderr, return_address - 1, tty_config) catch return; + } } } @@ -199,19 +203,21 @@ pub fn captureStackTrace(first_address: ?usize, stack_trace: *builtin.StackTrace /// Tries to print a stack trace to stderr, unbuffered, and ignores any error returned. /// TODO multithreaded awareness pub fn dumpStackTrace(stack_trace: builtin.StackTrace) void { - const stderr = getStderrStream(); - if (builtin.strip_debug_info) { - noasync stderr.print("Unable to dump stack trace: debug info stripped\n", .{}) catch return; - return; + noasync { + const stderr = getStderrStream(); + if (builtin.strip_debug_info) { + stderr.print("Unable to dump stack trace: debug info stripped\n", .{}) catch return; + return; + } + const debug_info = getSelfDebugInfo() catch |err| { + stderr.print("Unable to dump stack trace: Unable to open debug info: {}\n", .{@errorName(err)}) catch return; + return; + }; + writeStackTrace(stack_trace, stderr, getDebugInfoAllocator(), debug_info, detectTTYConfig()) catch |err| { + stderr.print("Unable to dump stack trace: {}\n", .{@errorName(err)}) catch return; + return; + }; } - const debug_info = getSelfDebugInfo() catch |err| { - noasync stderr.print("Unable to dump stack trace: Unable to open debug info: {}\n", .{@errorName(err)}) catch return; - return; - }; - writeStackTrace(stack_trace, stderr, getDebugInfoAllocator(), debug_info, detectTTYConfig()) catch |err| { - noasync stderr.print("Unable to dump stack trace: {}\n", .{@errorName(err)}) catch return; - return; - }; } /// This function invokes undefined behavior when `ok` is `false`. @@ -255,7 +261,7 @@ pub fn panicExtra(trace: ?*const builtin.StackTrace, first_trace_addr: ?usize, c resetSegfaultHandler(); } - switch (panic_stage) { + noasync switch (panic_stage) { 0 => { panic_stage = 1; @@ -267,7 +273,7 @@ pub fn panicExtra(trace: ?*const builtin.StackTrace, first_trace_addr: ?usize, c defer held.release(); const stderr = getStderrStream(); - noasync stderr.print(format ++ "\n", args) catch os.abort(); + stderr.print(format ++ "\n", args) catch os.abort(); if (trace) |t| { dumpStackTrace(t.*); } @@ -292,12 +298,12 @@ pub fn panicExtra(trace: ?*const builtin.StackTrace, first_trace_addr: ?usize, c // we're still holding the mutex but that's fine as we're going to // call abort() const stderr = getStderrStream(); - noasync stderr.print("Panicked during a panic. Aborting.\n", .{}) catch os.abort(); + stderr.print("Panicked during a panic. Aborting.\n", .{}) catch os.abort(); }, else => { // Panicked while printing "Panicked during a panic." }, - } + }; os.abort(); } diff --git a/lib/std/event/loop.zig b/lib/std/event/loop.zig index f0ac85d4f0..6337911cb6 100644 --- a/lib/std/event/loop.zig +++ b/lib/std/event/loop.zig @@ -4,19 +4,27 @@ const root = @import("root"); const assert = std.debug.assert; const testing = std.testing; const mem = std.mem; -const AtomicRmwOp = builtin.AtomicRmwOp; -const AtomicOrder = builtin.AtomicOrder; const os = std.os; const windows = os.windows; const maxInt = std.math.maxInt; const Thread = std.Thread; +const is_windows = std.Target.current.os.tag == .windows; + pub const Loop = struct { next_tick_queue: std.atomic.Queue(anyframe), os_data: OsData, final_resume_node: ResumeNode, pending_event_count: usize, extra_threads: []*Thread, + /// TODO change this to a pool of configurable number of threads + /// and rename it to be not file-system-specific. it will become + /// a thread pool for turning non-CPU-bound blocking things into + /// async things. A fallback for any missing OS-specific API. + fs_thread: *Thread, + fs_queue: std.atomic.Queue(Request), + fs_end_request: Request.Node, + fs_thread_wakeup: std.ResetEvent, /// For resources that have the same lifetime as the `Loop`. /// This is only used by `Loop` for the thread pool and associated resources. @@ -143,7 +151,12 @@ pub const Loop = struct { .handle = undefined, .overlapped = ResumeNode.overlapped_init, }, + .fs_end_request = .{ .data = .{ .msg = .end, .finish = .NoAction } }, + .fs_queue = std.atomic.Queue(Request).init(), + .fs_thread = undefined, + .fs_thread_wakeup = std.ResetEvent.init(), }; + errdefer self.fs_thread_wakeup.deinit(); errdefer self.arena.deinit(); // We need at least one of these in case the fs thread wants to use onNextTick @@ -158,10 +171,19 @@ pub const Loop = struct { try self.initOsData(extra_thread_count); errdefer self.deinitOsData(); + + if (!builtin.single_threaded) { + self.fs_thread = try Thread.spawn(self, posixFsRun); + } + errdefer if (!builtin.single_threaded) { + self.posixFsRequest(&self.fs_end_request); + self.fs_thread.wait(); + }; } pub fn deinit(self: *Loop) void { self.deinitOsData(); + self.fs_thread_wakeup.deinit(); self.arena.deinit(); self.* = undefined; } @@ -173,21 +195,10 @@ pub const Loop = struct { const wakeup_bytes = [_]u8{0x1} ** 8; fn initOsData(self: *Loop, extra_thread_count: usize) InitOsDataError!void { - switch (builtin.os.tag) { + noasync switch (builtin.os.tag) { .linux => { - self.os_data.fs_queue = std.atomic.Queue(Request).init(); - self.os_data.fs_queue_item = 0; - // we need another thread for the file system because Linux does not have an async - // file system I/O API. - self.os_data.fs_end_request = Request.Node{ - .data = Request{ - .msg = .end, - .finish = .NoAction, - }, - }; - errdefer { - while (self.available_eventfd_resume_nodes.pop()) |node| noasync os.close(node.data.eventfd); + while (self.available_eventfd_resume_nodes.pop()) |node| os.close(node.data.eventfd); } for (self.eventfd_resume_nodes) |*eventfd_node| { eventfd_node.* = std.atomic.Stack(ResumeNode.EventFd).Node{ @@ -206,10 +217,10 @@ pub const Loop = struct { } self.os_data.epollfd = try os.epoll_create1(os.EPOLL_CLOEXEC); - errdefer noasync os.close(self.os_data.epollfd); + errdefer os.close(self.os_data.epollfd); self.os_data.final_eventfd = try os.eventfd(0, os.EFD_CLOEXEC | os.EFD_NONBLOCK); - errdefer noasync os.close(self.os_data.final_eventfd); + errdefer os.close(self.os_data.final_eventfd); self.os_data.final_eventfd_event = os.epoll_event{ .events = os.EPOLLIN, @@ -222,12 +233,6 @@ pub const Loop = struct { &self.os_data.final_eventfd_event, ); - self.os_data.fs_thread = try Thread.spawn(self, posixFsRun); - errdefer { - self.posixFsRequest(&self.os_data.fs_end_request); - self.os_data.fs_thread.wait(); - } - if (builtin.single_threaded) { assert(extra_thread_count == 0); return; @@ -236,7 +241,7 @@ pub const Loop = struct { var extra_thread_index: usize = 0; errdefer { // writing 8 bytes to an eventfd cannot fail - const amt = noasync os.write(self.os_data.final_eventfd, &wakeup_bytes) catch unreachable; + const amt = os.write(self.os_data.final_eventfd, &wakeup_bytes) catch unreachable; assert(amt == wakeup_bytes.len); while (extra_thread_index != 0) { extra_thread_index -= 1; @@ -249,22 +254,7 @@ pub const Loop = struct { }, .macosx, .freebsd, .netbsd, .dragonfly => { self.os_data.kqfd = try os.kqueue(); - errdefer noasync os.close(self.os_data.kqfd); - - self.os_data.fs_kqfd = try os.kqueue(); - errdefer noasync os.close(self.os_data.fs_kqfd); - - self.os_data.fs_queue = std.atomic.Queue(Request).init(); - // we need another thread for the file system because Darwin does not have an async - // file system I/O API. - self.os_data.fs_end_request = Request.Node{ - .prev = undefined, - .next = undefined, - .data = Request{ - .msg = .end, - .finish = .NoAction, - }, - }; + errdefer os.close(self.os_data.kqfd); const empty_kevs = &[0]os.Kevent{}; @@ -310,30 +300,6 @@ pub const Loop = struct { self.os_data.final_kevent.flags = os.EV_ENABLE; self.os_data.final_kevent.fflags = os.NOTE_TRIGGER; - self.os_data.fs_kevent_wake = os.Kevent{ - .ident = 0, - .filter = os.EVFILT_USER, - .flags = os.EV_ADD | os.EV_ENABLE, - .fflags = os.NOTE_TRIGGER, - .data = 0, - .udata = undefined, - }; - - self.os_data.fs_kevent_wait = os.Kevent{ - .ident = 0, - .filter = os.EVFILT_USER, - .flags = os.EV_ADD | os.EV_CLEAR, - .fflags = 0, - .data = 0, - .udata = undefined, - }; - - self.os_data.fs_thread = try Thread.spawn(self, posixFsRun); - errdefer { - self.posixFsRequest(&self.os_data.fs_end_request); - self.os_data.fs_thread.wait(); - } - if (builtin.single_threaded) { assert(extra_thread_count == 0); return; @@ -401,25 +367,24 @@ pub const Loop = struct { } }, else => {}, - } + }; } fn deinitOsData(self: *Loop) void { - switch (builtin.os.tag) { + noasync switch (builtin.os.tag) { .linux => { - noasync os.close(self.os_data.final_eventfd); - while (self.available_eventfd_resume_nodes.pop()) |node| noasync os.close(node.data.eventfd); - noasync os.close(self.os_data.epollfd); + os.close(self.os_data.final_eventfd); + while (self.available_eventfd_resume_nodes.pop()) |node| os.close(node.data.eventfd); + os.close(self.os_data.epollfd); }, .macosx, .freebsd, .netbsd, .dragonfly => { - noasync os.close(self.os_data.kqfd); - noasync os.close(self.os_data.fs_kqfd); + os.close(self.os_data.kqfd); }, .windows => { windows.CloseHandle(self.os_data.io_port); }, else => {}, - } + }; } /// resume_node must live longer than the anyframe that it holds a reference to. @@ -635,7 +600,7 @@ pub const Loop = struct { .freebsd, .netbsd, .dragonfly, - => self.os_data.fs_thread.wait(), + => self.fs_thread.wait(), else => {}, } @@ -672,23 +637,25 @@ pub const Loop = struct { /// call finishOneEvent when done pub fn beginOneEvent(self: *Loop) void { - _ = @atomicRmw(usize, &self.pending_event_count, AtomicRmwOp.Add, 1, AtomicOrder.SeqCst); + _ = @atomicRmw(usize, &self.pending_event_count, .Add, 1, .SeqCst); } pub fn finishOneEvent(self: *Loop) void { - const prev = @atomicRmw(usize, &self.pending_event_count, AtomicRmwOp.Sub, 1, AtomicOrder.SeqCst); - if (prev == 1) { + noasync { + const prev = @atomicRmw(usize, &self.pending_event_count, .Sub, 1, .SeqCst); + if (prev != 1) return; + // cause all the threads to stop + self.posixFsRequest(&self.fs_end_request); + switch (builtin.os.tag) { .linux => { - self.posixFsRequest(&self.os_data.fs_end_request); // writing 8 bytes to an eventfd cannot fail - const amt = noasync os.write(self.os_data.final_eventfd, &wakeup_bytes) catch unreachable; + const amt = os.write(self.os_data.final_eventfd, &wakeup_bytes) catch unreachable; assert(amt == wakeup_bytes.len); return; }, .macosx, .freebsd, .netbsd, .dragonfly => { - self.posixFsRequest(&self.os_data.fs_end_request); const final_kevent = @as(*const [1]os.Kevent, &self.os_data.final_kevent); const empty_kevs = &[0]os.Kevent{}; // cannot fail because we already added it and this just enables it @@ -1041,73 +1008,55 @@ pub const Loop = struct { fn posixFsRequest(self: *Loop, request_node: *Request.Node) void { self.beginOneEvent(); // finished in posixFsRun after processing the msg - self.os_data.fs_queue.put(request_node); - switch (builtin.os.tag) { - .macosx, .freebsd, .netbsd, .dragonfly => { - const fs_kevs = @as(*const [1]os.Kevent, &self.os_data.fs_kevent_wake); - const empty_kevs = &[0]os.Kevent{}; - _ = os.kevent(self.os_data.fs_kqfd, fs_kevs, empty_kevs, null) catch unreachable; - }, - .linux => { - @atomicStore(i32, &self.os_data.fs_queue_item, 1, AtomicOrder.SeqCst); - const rc = os.linux.futex_wake(&self.os_data.fs_queue_item, os.linux.FUTEX_WAKE, 1); - switch (os.linux.getErrno(rc)) { - 0 => {}, - os.EINVAL => unreachable, - else => unreachable, - } - }, - else => @compileError("Unsupported OS"), - } + self.fs_queue.put(request_node); + self.fs_thread_wakeup.set(); } fn posixFsCancel(self: *Loop, request_node: *Request.Node) void { - if (self.os_data.fs_queue.remove(request_node)) { + if (self.fs_queue.remove(request_node)) { self.finishOneEvent(); } } - // TODO make this whole function noasync - // https://github.com/ziglang/zig/issues/3157 fn posixFsRun(self: *Loop) void { - while (true) { - if (builtin.os.tag == .linux) { - @atomicStore(i32, &self.os_data.fs_queue_item, 0, .SeqCst); - } - while (self.os_data.fs_queue.get()) |node| { + noasync while (true) { + self.fs_thread_wakeup.reset(); + while (self.fs_queue.get()) |node| { switch (node.data.msg) { .end => return, .read => |*msg| { - msg.result = noasync os.read(msg.fd, msg.buf); + msg.result = os.read(msg.fd, msg.buf); }, .readv => |*msg| { - msg.result = noasync os.readv(msg.fd, msg.iov); + msg.result = os.readv(msg.fd, msg.iov); }, .write => |*msg| { - msg.result = noasync os.write(msg.fd, msg.bytes); + msg.result = os.write(msg.fd, msg.bytes); }, .writev => |*msg| { - msg.result = noasync os.writev(msg.fd, msg.iov); + msg.result = os.writev(msg.fd, msg.iov); }, .pwritev => |*msg| { - msg.result = noasync os.pwritev(msg.fd, msg.iov, msg.offset); + msg.result = os.pwritev(msg.fd, msg.iov, msg.offset); }, .pread => |*msg| { - msg.result = noasync os.pread(msg.fd, msg.buf, msg.offset); + msg.result = os.pread(msg.fd, msg.buf, msg.offset); }, .preadv => |*msg| { - msg.result = noasync os.preadv(msg.fd, msg.iov, msg.offset); + msg.result = os.preadv(msg.fd, msg.iov, msg.offset); }, .open => |*msg| { - msg.result = noasync os.openZ(msg.path, msg.flags, msg.mode); + if (is_windows) unreachable; // TODO + msg.result = os.openZ(msg.path, msg.flags, msg.mode); }, .openat => |*msg| { - msg.result = noasync os.openatZ(msg.fd, msg.path, msg.flags, msg.mode); + if (is_windows) unreachable; // TODO + msg.result = os.openatZ(msg.fd, msg.path, msg.flags, msg.mode); }, .faccessat => |*msg| { - msg.result = noasync os.faccessatZ(msg.dirfd, msg.path, msg.mode, msg.flags); + msg.result = os.faccessatZ(msg.dirfd, msg.path, msg.mode, msg.flags); }, - .close => |*msg| noasync os.close(msg.fd), + .close => |*msg| os.close(msg.fd), } switch (node.data.finish) { .TickNode => |*tick_node| self.onNextTick(tick_node), @@ -1115,22 +1064,8 @@ pub const Loop = struct { } self.finishOneEvent(); } - switch (builtin.os.tag) { - .linux => { - const rc = os.linux.futex_wait(&self.os_data.fs_queue_item, os.linux.FUTEX_WAIT, 0, null); - switch (os.linux.getErrno(rc)) { - 0, os.EINTR, os.EAGAIN => continue, - else => unreachable, - } - }, - .macosx, .freebsd, .netbsd, .dragonfly => { - const fs_kevs = @as(*const [1]os.Kevent, &self.os_data.fs_kevent_wait); - var out_kevs: [1]os.Kevent = undefined; - _ = os.kevent(self.os_data.fs_kqfd, fs_kevs, out_kevs[0..], null) catch unreachable; - }, - else => @compileError("Unsupported OS"), - } - } + self.fs_thread_wakeup.wait(); + }; } const OsData = switch (builtin.os.tag) { @@ -1146,22 +1081,12 @@ pub const Loop = struct { const KEventData = struct { kqfd: i32, final_kevent: os.Kevent, - fs_kevent_wake: os.Kevent, - fs_kevent_wait: os.Kevent, - fs_thread: *Thread, - fs_kqfd: i32, - fs_queue: std.atomic.Queue(Request), - fs_end_request: Request.Node, }; const LinuxOsData = struct { epollfd: i32, final_eventfd: i32, final_eventfd_event: os.linux.epoll_event, - fs_thread: *Thread, - fs_queue_item: i32, - fs_queue: std.atomic.Queue(Request), - fs_end_request: Request.Node, }; pub const Request = struct { @@ -1302,11 +1227,11 @@ test "std.event.Loop - basic" { loop.run(); } -async fn testEventLoop() i32 { +fn testEventLoop() i32 { return 1234; } -async fn testEventLoop2(h: anyframe->i32, did_it: *bool) void { +fn testEventLoop2(h: anyframe->i32, did_it: *bool) void { const value = await h; testing.expect(value == 1234); did_it.* = true; diff --git a/lib/std/fs.zig b/lib/std/fs.zig index 99b43a66e3..7dcfc9261c 100644 --- a/lib/std/fs.zig +++ b/lib/std/fs.zig @@ -734,7 +734,7 @@ pub const Dir = struct { .dir = self.fd, .access_mask = w.SYNCHRONIZE | w.GENERIC_WRITE | read_flag, .share_access = switch (flags.lock) { - .None => @as(?w.ULONG, null), + .None => w.FILE_SHARE_WRITE | w.FILE_SHARE_READ | w.FILE_SHARE_DELETE, .Shared => w.FILE_SHARE_READ | w.FILE_SHARE_DELETE, .Exclusive => w.FILE_SHARE_DELETE, }, diff --git a/lib/std/os.zig b/lib/std/os.zig index 05d8b60a2d..39f5d36ddf 100644 --- a/lib/std/os.zig +++ b/lib/std/os.zig @@ -854,8 +854,11 @@ pub const OpenError = error{ /// Open and possibly create a file. Keeps trying if it gets interrupted. /// See also `openC`. -/// TODO support windows pub fn open(file_path: []const u8, flags: u32, perm: usize) OpenError!fd_t { + if (std.Target.current.os.tag == .windows) { + const file_path_w = try windows.sliceToPrefixedFileW(file_path); + return openW(&file_path_w, flags, perm); + } const file_path_c = try toPosixPath(file_path); return openZ(&file_path_c, flags, perm); } @@ -864,8 +867,11 @@ pub const openC = @compileError("deprecated: renamed to openZ"); /// Open and possibly create a file. Keeps trying if it gets interrupted. /// See also `open`. -/// TODO support windows pub fn openZ(file_path: [*:0]const u8, flags: u32, perm: usize) OpenError!fd_t { + if (std.Target.current.os.tag == .windows) { + const file_path_w = try windows.cStrToPrefixedFileW(file_path); + return openW(&file_path_w, flags, perm); + } while (true) { const rc = system.open(file_path, flags, perm); switch (errno(rc)) { @@ -895,6 +901,13 @@ pub fn openZ(file_path: [*:0]const u8, flags: u32, perm: usize) OpenError!fd_t { } } +/// Windows-only. The path parameter is +/// [WTF-16](https://simonsapin.github.io/wtf-8/#potentially-ill-formed-utf-16) encoded. +/// Translates the POSIX open API call to a Windows API call. +pub fn openW(file_path_w: []const u16, flags: u32, perm: usize) OpenError!fd_t { + @compileError("TODO implement openW for windows"); +} + /// Open and possibly create a file. Keeps trying if it gets interrupted. /// `file_path` is relative to the open directory handle `dir_fd`. /// See also `openatC`. @@ -1683,7 +1696,7 @@ pub fn renameatW( .dir = old_dir_fd, .access_mask = windows.SYNCHRONIZE | windows.GENERIC_WRITE | windows.DELETE, .creation = windows.FILE_OPEN, - .enable_async_io = false, + .io_mode = .blocking, }) catch |err| switch (err) { error.WouldBlock => unreachable, // Not possible without `.share_access_nonblocking = true`. else => |e| return e, diff --git a/lib/std/os/windows.zig b/lib/std/os/windows.zig index 3e55a825de..3ef3b63086 100644 --- a/lib/std/os/windows.zig +++ b/lib/std/os/windows.zig @@ -116,10 +116,10 @@ pub const OpenFileOptions = struct { /// TODO when share_access_nonblocking is false, this implementation uses /// untinterruptible sleep() to block. This is not the final iteration of the API. pub fn OpenFile(sub_path_w: []const u16, options: OpenFileOptions) OpenError!HANDLE { - if (sub_path_w[0] == '.' and sub_path_w[1] == 0) { + if (mem.eql(u16, sub_path_w, ".")) { return error.IsDir; } - if (sub_path_w[0] == '.' and sub_path_w[1] == '.' and sub_path_w[2] == 0) { + if (mem.eql(u16, sub_path_w, "..")) { return error.IsDir; } diff --git a/lib/std/reset_event.zig b/lib/std/reset_event.zig index c28db809ca..860f494f3f 100644 --- a/lib/std/reset_event.zig +++ b/lib/std/reset_event.zig @@ -52,7 +52,7 @@ pub const ResetEvent = struct { /// Wait for the event to be set by blocking the current thread. /// A timeout in nanoseconds can be provided as a hint for how - /// long the thread should block on the unset event before throwind error.TimedOut. + /// long the thread should block on the unset event before throwing error.TimedOut. pub fn timedWait(self: *ResetEvent, timeout_ns: u64) !void { return self.os_event.wait(timeout_ns); } |
