mirror of
https://github.com/ziglang/zig.git
synced 2025-12-06 14:23:09 +00:00
cleanup and fixes. behavior tests passing with evented I/O
This commit is contained in:
parent
988031c07c
commit
45bce27b8f
@ -433,26 +433,17 @@ pub const ChildProcess = struct {
|
|||||||
// we are the parent
|
// we are the parent
|
||||||
const pid = @intCast(i32, pid_result);
|
const pid = @intCast(i32, pid_result);
|
||||||
if (self.stdin_behavior == StdIo.Pipe) {
|
if (self.stdin_behavior == StdIo.Pipe) {
|
||||||
self.stdin = File{
|
self.stdin = File{ .handle = stdin_pipe[1] };
|
||||||
.handle = stdin_pipe[1],
|
|
||||||
.io_mode = std.io.mode,
|
|
||||||
};
|
|
||||||
} else {
|
} else {
|
||||||
self.stdin = null;
|
self.stdin = null;
|
||||||
}
|
}
|
||||||
if (self.stdout_behavior == StdIo.Pipe) {
|
if (self.stdout_behavior == StdIo.Pipe) {
|
||||||
self.stdout = File{
|
self.stdout = File{ .handle = stdout_pipe[0] };
|
||||||
.handle = stdout_pipe[0],
|
|
||||||
.io_mode = std.io.mode,
|
|
||||||
};
|
|
||||||
} else {
|
} else {
|
||||||
self.stdout = null;
|
self.stdout = null;
|
||||||
}
|
}
|
||||||
if (self.stderr_behavior == StdIo.Pipe) {
|
if (self.stderr_behavior == StdIo.Pipe) {
|
||||||
self.stderr = File{
|
self.stderr = File{ .handle = stderr_pipe[0] };
|
||||||
.handle = stderr_pipe[0],
|
|
||||||
.io_mode = std.io.mode,
|
|
||||||
};
|
|
||||||
} else {
|
} else {
|
||||||
self.stderr = null;
|
self.stderr = null;
|
||||||
}
|
}
|
||||||
@ -835,8 +826,8 @@ const ErrInt = std.meta.Int(false, @sizeOf(anyerror) * 8);
|
|||||||
fn writeIntFd(fd: i32, value: ErrInt) !void {
|
fn writeIntFd(fd: i32, value: ErrInt) !void {
|
||||||
const file = File{
|
const file = File{
|
||||||
.handle = fd,
|
.handle = fd,
|
||||||
.io_mode = .blocking,
|
.capable_io_mode = .blocking,
|
||||||
.async_block_allowed = File.async_block_allowed_yes,
|
.intended_io_mode = .blocking,
|
||||||
};
|
};
|
||||||
file.outStream().writeIntNative(u64, @intCast(u64, value)) catch return error.SystemResources;
|
file.outStream().writeIntNative(u64, @intCast(u64, value)) catch return error.SystemResources;
|
||||||
}
|
}
|
||||||
@ -844,8 +835,8 @@ fn writeIntFd(fd: i32, value: ErrInt) !void {
|
|||||||
fn readIntFd(fd: i32) !ErrInt {
|
fn readIntFd(fd: i32) !ErrInt {
|
||||||
const file = File{
|
const file = File{
|
||||||
.handle = fd,
|
.handle = fd,
|
||||||
.io_mode = .blocking,
|
.capable_io_mode = .blocking,
|
||||||
.async_block_allowed = File.async_block_allowed_yes,
|
.intended_io_mode = .blocking,
|
||||||
};
|
};
|
||||||
return @intCast(ErrInt, file.inStream().readIntNative(u64) catch return error.SystemResources);
|
return @intCast(ErrInt, file.inStream().readIntNative(u64) catch return error.SystemResources);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -667,7 +667,7 @@ pub fn openSelfDebugInfo(allocator: *mem.Allocator) anyerror!DebugInfo {
|
|||||||
/// TODO resources https://github.com/ziglang/zig/issues/4353
|
/// TODO resources https://github.com/ziglang/zig/issues/4353
|
||||||
fn openCoffDebugInfo(allocator: *mem.Allocator, coff_file_path: [:0]const u16) !ModuleDebugInfo {
|
fn openCoffDebugInfo(allocator: *mem.Allocator, coff_file_path: [:0]const u16) !ModuleDebugInfo {
|
||||||
noasync {
|
noasync {
|
||||||
const coff_file = try std.fs.openFileAbsoluteW(coff_file_path.ptr, .{});
|
const coff_file = try std.fs.openFileAbsoluteW(coff_file_path, .{ .intended_io_mode = .blocking });
|
||||||
errdefer coff_file.close();
|
errdefer coff_file.close();
|
||||||
|
|
||||||
const coff_obj = try allocator.create(coff.Coff);
|
const coff_obj = try allocator.create(coff.Coff);
|
||||||
@ -1003,7 +1003,7 @@ fn openMachODebugInfo(allocator: *mem.Allocator, macho_file_path: []const u8) !M
|
|||||||
fn printLineFromFileAnyOs(out_stream: var, line_info: LineInfo) !void {
|
fn printLineFromFileAnyOs(out_stream: var, line_info: LineInfo) !void {
|
||||||
// Need this to always block even in async I/O mode, because this could potentially
|
// Need this to always block even in async I/O mode, because this could potentially
|
||||||
// be called from e.g. the event loop code crashing.
|
// be called from e.g. the event loop code crashing.
|
||||||
var f = try fs.cwd().openFile(line_info.file_name, .{ .always_blocking = true });
|
var f = try fs.cwd().openFile(line_info.file_name, .{ .intended_io_mode = .blocking });
|
||||||
defer f.close();
|
defer f.close();
|
||||||
// TODO fstat and make sure that the file has the correct size
|
// TODO fstat and make sure that the file has the correct size
|
||||||
|
|
||||||
@ -1051,7 +1051,7 @@ const MachoSymbol = struct {
|
|||||||
|
|
||||||
fn mapWholeFile(path: []const u8) ![]align(mem.page_size) const u8 {
|
fn mapWholeFile(path: []const u8) ![]align(mem.page_size) const u8 {
|
||||||
noasync {
|
noasync {
|
||||||
const file = try fs.cwd().openFile(path, .{ .always_blocking = true });
|
const file = try fs.cwd().openFile(path, .{ .intended_io_mode = .blocking });
|
||||||
defer file.close();
|
defer file.close();
|
||||||
|
|
||||||
const file_len = try math.cast(usize, try file.getEndPos());
|
const file_len = try math.cast(usize, try file.getEndPos());
|
||||||
|
|||||||
@ -8,6 +8,8 @@ const Allocator = std.mem.Allocator;
|
|||||||
const assert = std.debug.assert;
|
const assert = std.debug.assert;
|
||||||
const math = std.math;
|
const math = std.math;
|
||||||
|
|
||||||
|
const is_darwin = std.Target.current.os.tag.isDarwin();
|
||||||
|
|
||||||
pub const path = @import("fs/path.zig");
|
pub const path = @import("fs/path.zig");
|
||||||
pub const File = @import("fs/file.zig").File;
|
pub const File = @import("fs/file.zig").File;
|
||||||
|
|
||||||
@ -597,8 +599,11 @@ pub const Dir = struct {
|
|||||||
|
|
||||||
// Use the O_ locking flags if the os supports them
|
// Use the O_ locking flags if the os supports them
|
||||||
// (Or if it's darwin, as darwin's `open` doesn't support the O_SYNC flag)
|
// (Or if it's darwin, as darwin's `open` doesn't support the O_SYNC flag)
|
||||||
const has_flock_open_flags = @hasDecl(os, "O_EXLOCK") and !builtin.os.tag.isDarwin();
|
const has_flock_open_flags = @hasDecl(os, "O_EXLOCK") and !is_darwin;
|
||||||
const nonblocking_lock_flag = if (has_flock_open_flags and flags.lock_nonblocking) (os.O_NONBLOCK | os.O_SYNC) else @as(u32, 0);
|
const nonblocking_lock_flag = if (has_flock_open_flags and flags.lock_nonblocking)
|
||||||
|
os.O_NONBLOCK | os.O_SYNC
|
||||||
|
else
|
||||||
|
@as(u32, 0);
|
||||||
const lock_flag: u32 = if (has_flock_open_flags) switch (flags.lock) {
|
const lock_flag: u32 = if (has_flock_open_flags) switch (flags.lock) {
|
||||||
.None => @as(u32, 0),
|
.None => @as(u32, 0),
|
||||||
.Shared => os.O_SHLOCK | nonblocking_lock_flag,
|
.Shared => os.O_SHLOCK | nonblocking_lock_flag,
|
||||||
@ -612,7 +617,7 @@ pub const Dir = struct {
|
|||||||
@as(u32, os.O_WRONLY)
|
@as(u32, os.O_WRONLY)
|
||||||
else
|
else
|
||||||
@as(u32, os.O_RDONLY);
|
@as(u32, os.O_RDONLY);
|
||||||
const fd = if (need_async_thread and !flags.always_blocking)
|
const fd = if (flags.intended_io_mode != .blocking)
|
||||||
try std.event.Loop.instance.?.openatZ(self.fd, sub_path, os_flags, 0)
|
try std.event.Loop.instance.?.openatZ(self.fd, sub_path, os_flags, 0)
|
||||||
else
|
else
|
||||||
try os.openatZ(self.fd, sub_path, os_flags, 0);
|
try os.openatZ(self.fd, sub_path, os_flags, 0);
|
||||||
@ -629,11 +634,8 @@ pub const Dir = struct {
|
|||||||
|
|
||||||
return File{
|
return File{
|
||||||
.handle = fd,
|
.handle = fd,
|
||||||
.io_mode = .blocking,
|
.capable_io_mode = .blocking,
|
||||||
.async_block_allowed = if (flags.always_blocking)
|
.intended_io_mode = flags.intended_io_mode,
|
||||||
File.async_block_allowed_yes
|
|
||||||
else
|
|
||||||
File.async_block_allowed_no,
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -648,19 +650,16 @@ pub const Dir = struct {
|
|||||||
(if (flags.read) @as(u32, w.GENERIC_READ) else 0) |
|
(if (flags.read) @as(u32, w.GENERIC_READ) else 0) |
|
||||||
(if (flags.write) @as(u32, w.GENERIC_WRITE) else 0),
|
(if (flags.write) @as(u32, w.GENERIC_WRITE) else 0),
|
||||||
.share_access = switch (flags.lock) {
|
.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,
|
.Shared => w.FILE_SHARE_READ | w.FILE_SHARE_DELETE,
|
||||||
.Exclusive => w.FILE_SHARE_DELETE,
|
.Exclusive => w.FILE_SHARE_DELETE,
|
||||||
},
|
},
|
||||||
.share_access_nonblocking = flags.lock_nonblocking,
|
.share_access_nonblocking = flags.lock_nonblocking,
|
||||||
.creation = w.FILE_OPEN,
|
.creation = w.FILE_OPEN,
|
||||||
.enable_async_io = std.io.is_async and !flags.always_blocking,
|
.io_mode = flags.intended_io_mode,
|
||||||
}),
|
}),
|
||||||
.io_mode = .blocking,
|
.capable_io_mode = std.io.default_mode,
|
||||||
.async_block_allowed = if (flags.always_blocking)
|
.intended_io_mode = flags.intended_io_mode,
|
||||||
File.async_block_allowed_yes
|
|
||||||
else
|
|
||||||
File.async_block_allowed_no,
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -687,8 +686,11 @@ pub const Dir = struct {
|
|||||||
|
|
||||||
// Use the O_ locking flags if the os supports them
|
// Use the O_ locking flags if the os supports them
|
||||||
// (Or if it's darwin, as darwin's `open` doesn't support the O_SYNC flag)
|
// (Or if it's darwin, as darwin's `open` doesn't support the O_SYNC flag)
|
||||||
const has_flock_open_flags = @hasDecl(os, "O_EXLOCK") and !builtin.os.tag.isDarwin();
|
const has_flock_open_flags = @hasDecl(os, "O_EXLOCK") and !is_darwin;
|
||||||
const nonblocking_lock_flag = if (has_flock_open_flags and flags.lock_nonblocking) (os.O_NONBLOCK | os.O_SYNC) else @as(u32, 0);
|
const nonblocking_lock_flag: u32 = if (has_flock_open_flags and flags.lock_nonblocking)
|
||||||
|
os.O_NONBLOCK | os.O_SYNC
|
||||||
|
else
|
||||||
|
0;
|
||||||
const lock_flag: u32 = if (has_flock_open_flags) switch (flags.lock) {
|
const lock_flag: u32 = if (has_flock_open_flags) switch (flags.lock) {
|
||||||
.None => @as(u32, 0),
|
.None => @as(u32, 0),
|
||||||
.Shared => os.O_SHLOCK,
|
.Shared => os.O_SHLOCK,
|
||||||
@ -700,7 +702,7 @@ pub const Dir = struct {
|
|||||||
(if (flags.truncate) @as(u32, os.O_TRUNC) else 0) |
|
(if (flags.truncate) @as(u32, os.O_TRUNC) else 0) |
|
||||||
(if (flags.read) @as(u32, os.O_RDWR) else os.O_WRONLY) |
|
(if (flags.read) @as(u32, os.O_RDWR) else os.O_WRONLY) |
|
||||||
(if (flags.exclusive) @as(u32, os.O_EXCL) else 0);
|
(if (flags.exclusive) @as(u32, os.O_EXCL) else 0);
|
||||||
const fd = if (need_async_thread)
|
const fd = if (flags.intended_io_mode != .blocking)
|
||||||
try std.event.Loop.instance.?.openatZ(self.fd, sub_path_c, os_flags, flags.mode)
|
try std.event.Loop.instance.?.openatZ(self.fd, sub_path_c, os_flags, flags.mode)
|
||||||
else
|
else
|
||||||
try os.openatZ(self.fd, sub_path_c, os_flags, flags.mode);
|
try os.openatZ(self.fd, sub_path_c, os_flags, flags.mode);
|
||||||
@ -715,7 +717,11 @@ pub const Dir = struct {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return File{ .handle = fd, .io_mode = .blocking };
|
return File{
|
||||||
|
.handle = fd,
|
||||||
|
.capable_io_mode = .blocking,
|
||||||
|
.intended_io_mode = flags.intended_io_mode,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Same as `createFile` but Windows-only and the path parameter is
|
/// Same as `createFile` but Windows-only and the path parameter is
|
||||||
@ -739,9 +745,10 @@ pub const Dir = struct {
|
|||||||
@as(u32, w.FILE_OVERWRITE_IF)
|
@as(u32, w.FILE_OVERWRITE_IF)
|
||||||
else
|
else
|
||||||
@as(u32, w.FILE_OPEN_IF),
|
@as(u32, w.FILE_OPEN_IF),
|
||||||
.enable_async_io = std.io.is_async,
|
.io_mode = flags.intended_io_mode,
|
||||||
}),
|
}),
|
||||||
.io_mode = .blocking,
|
.capable_io_mode = std.io.default_mode,
|
||||||
|
.intended_io_mode = flags.intended_io_mode,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1257,7 +1264,7 @@ pub const Dir = struct {
|
|||||||
@as(u32, os.W_OK)
|
@as(u32, os.W_OK)
|
||||||
else
|
else
|
||||||
@as(u32, os.F_OK);
|
@as(u32, os.F_OK);
|
||||||
const result = if (need_async_thread)
|
const result = if (need_async_thread and flags.intended_io_mode != .blocking)
|
||||||
std.event.Loop.instance.?.faccessatZ(self.fd, sub_path, os_mode, 0)
|
std.event.Loop.instance.?.faccessatZ(self.fd, sub_path, os_mode, 0)
|
||||||
else
|
else
|
||||||
os.faccessatZ(self.fd, sub_path, os_mode, 0);
|
os.faccessatZ(self.fd, sub_path, os_mode, 0);
|
||||||
@ -1399,8 +1406,8 @@ pub fn openFileAbsoluteZ(absolute_path_c: [*:0]const u8, flags: File.OpenFlags)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Same as `openFileAbsolute` but the path parameter is WTF-16 encoded.
|
/// Same as `openFileAbsolute` but the path parameter is WTF-16 encoded.
|
||||||
pub fn openFileAbsoluteW(absolute_path_w: [*:0]const u16, flags: File.OpenFlags) File.OpenError!File {
|
pub fn openFileAbsoluteW(absolute_path_w: []const u16, flags: File.OpenFlags) File.OpenError!File {
|
||||||
assert(path.isAbsoluteWindowsW(absolute_path_w));
|
assert(path.isAbsoluteWindowsWTF16(absolute_path_w));
|
||||||
return cwd().openFileW(absolute_path_w, flags);
|
return cwd().openFileW(absolute_path_w, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1617,7 +1624,7 @@ pub fn selfExePathAlloc(allocator: *Allocator) ![]u8 {
|
|||||||
/// been deleted, the file path looks something like `/a/b/c/exe (deleted)`.
|
/// been deleted, the file path looks something like `/a/b/c/exe (deleted)`.
|
||||||
/// TODO make the return type of this a null terminated pointer
|
/// TODO make the return type of this a null terminated pointer
|
||||||
pub fn selfExePath(out_buffer: *[MAX_PATH_BYTES]u8) SelfExePathError![]u8 {
|
pub fn selfExePath(out_buffer: *[MAX_PATH_BYTES]u8) SelfExePathError![]u8 {
|
||||||
if (comptime std.Target.current.isDarwin()) {
|
if (is_darwin) {
|
||||||
var u32_len: u32 = out_buffer.len;
|
var u32_len: u32 = out_buffer.len;
|
||||||
const rc = std.c._NSGetExecutablePath(out_buffer, &u32_len);
|
const rc = std.c._NSGetExecutablePath(out_buffer, &u32_len);
|
||||||
if (rc != 0) return error.NameTooLong;
|
if (rc != 0) return error.NameTooLong;
|
||||||
|
|||||||
@ -8,7 +8,6 @@ const assert = std.debug.assert;
|
|||||||
const windows = os.windows;
|
const windows = os.windows;
|
||||||
const Os = builtin.Os;
|
const Os = builtin.Os;
|
||||||
const maxInt = std.math.maxInt;
|
const maxInt = std.math.maxInt;
|
||||||
const need_async_thread = std.fs.need_async_thread;
|
|
||||||
|
|
||||||
pub const File = struct {
|
pub const File = struct {
|
||||||
/// The OS-specific file descriptor or file handle.
|
/// The OS-specific file descriptor or file handle.
|
||||||
@ -17,15 +16,14 @@ pub const File = struct {
|
|||||||
/// On some systems, such as Linux, file system file descriptors are incapable of non-blocking I/O.
|
/// On some systems, such as Linux, file system file descriptors are incapable of non-blocking I/O.
|
||||||
/// This forces us to perform asynchronous I/O on a dedicated thread, to achieve non-blocking
|
/// This forces us to perform asynchronous I/O on a dedicated thread, to achieve non-blocking
|
||||||
/// file-system I/O. To do this, `File` must be aware of whether it is a file system file descriptor,
|
/// file-system I/O. To do this, `File` must be aware of whether it is a file system file descriptor,
|
||||||
/// or, more specifically, whether the I/O is blocking.
|
/// or, more specifically, whether the I/O is always blocking.
|
||||||
io_mode: io.Mode,
|
capable_io_mode: io.ModeOverride = io.default_mode,
|
||||||
|
|
||||||
/// Even when 'std.io.mode' is async, it is still sometimes desirable to perform blocking I/O, although
|
/// Furthermore, even when `std.io.mode` is async, it is still sometimes desirable to perform blocking I/O,
|
||||||
/// not by default. For example, when printing a stack trace to stderr.
|
/// although not by default. For example, when printing a stack trace to stderr.
|
||||||
async_block_allowed: @TypeOf(async_block_allowed_no) = async_block_allowed_no,
|
/// This field tracks both by acting as an overriding I/O mode. When not building in async I/O mode,
|
||||||
|
/// the type only has the `.blocking` tag, making it a zero-bit type.
|
||||||
pub const async_block_allowed_yes = if (io.is_async) true else {};
|
intended_io_mode: io.ModeOverride = io.default_mode,
|
||||||
pub const async_block_allowed_no = if (io.is_async) false else {};
|
|
||||||
|
|
||||||
pub const Mode = os.mode_t;
|
pub const Mode = os.mode_t;
|
||||||
|
|
||||||
@ -36,9 +34,7 @@ pub const File = struct {
|
|||||||
|
|
||||||
pub const OpenError = windows.CreateFileError || os.OpenError || os.FlockError;
|
pub const OpenError = windows.CreateFileError || os.OpenError || os.FlockError;
|
||||||
|
|
||||||
pub const Lock = enum {
|
pub const Lock = enum { None, Shared, Exclusive };
|
||||||
None, Shared, Exclusive
|
|
||||||
};
|
|
||||||
|
|
||||||
/// TODO https://github.com/ziglang/zig/issues/3802
|
/// TODO https://github.com/ziglang/zig/issues/3802
|
||||||
pub const OpenFlags = struct {
|
pub const OpenFlags = struct {
|
||||||
@ -62,15 +58,16 @@ pub const File = struct {
|
|||||||
|
|
||||||
/// Sets whether or not to wait until the file is locked to return. If set to true,
|
/// Sets whether or not to wait until the file is locked to return. If set to true,
|
||||||
/// `error.WouldBlock` will be returned. Otherwise, the file will wait until the file
|
/// `error.WouldBlock` will be returned. Otherwise, the file will wait until the file
|
||||||
/// is available to proceed. In async I/O mode, non-blocking at the OS level is always
|
/// is available to proceed.
|
||||||
/// used, and `true` means `error.WouldBlock` is returned, and `false` means
|
/// In async I/O mode, non-blocking at the OS level is
|
||||||
/// `error.WouldBlock` is handled by the event loop.
|
/// determined by `intended_io_mode`, and `true` means `error.WouldBlock` is returned,
|
||||||
|
/// and `false` means `error.WouldBlock` is handled by the event loop.
|
||||||
lock_nonblocking: bool = false,
|
lock_nonblocking: bool = false,
|
||||||
|
|
||||||
/// This prevents `O_NONBLOCK` from being passed even if `std.io.is_async`.
|
/// Setting this to `.blocking` prevents `O_NONBLOCK` from being passed even
|
||||||
/// It allows the use of `noasync` when calling functions related to opening
|
/// if `std.io.is_async`. It allows the use of `noasync` when calling functions
|
||||||
/// the file, reading, writing, as well as locking functionality.
|
/// related to opening the file, reading, writing, and locking.
|
||||||
always_blocking: bool = false,
|
intended_io_mode: io.ModeOverride = io.default_mode,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// TODO https://github.com/ziglang/zig/issues/3802
|
/// TODO https://github.com/ziglang/zig/issues/3802
|
||||||
@ -104,17 +101,25 @@ pub const File = struct {
|
|||||||
/// Sets whether or not to wait until the file is locked to return. If set to true,
|
/// Sets whether or not to wait until the file is locked to return. If set to true,
|
||||||
/// `error.WouldBlock` will be returned. Otherwise, the file will wait until the file
|
/// `error.WouldBlock` will be returned. Otherwise, the file will wait until the file
|
||||||
/// is available to proceed.
|
/// is available to proceed.
|
||||||
|
/// In async I/O mode, non-blocking at the OS level is
|
||||||
|
/// determined by `intended_io_mode`, and `true` means `error.WouldBlock` is returned,
|
||||||
|
/// and `false` means `error.WouldBlock` is handled by the event loop.
|
||||||
lock_nonblocking: bool = false,
|
lock_nonblocking: bool = false,
|
||||||
|
|
||||||
/// For POSIX systems this is the file system mode the file will
|
/// For POSIX systems this is the file system mode the file will
|
||||||
/// be created with.
|
/// be created with.
|
||||||
mode: Mode = default_mode,
|
mode: Mode = default_mode,
|
||||||
|
|
||||||
|
/// Setting this to `.blocking` prevents `O_NONBLOCK` from being passed even
|
||||||
|
/// if `std.io.is_async`. It allows the use of `noasync` when calling functions
|
||||||
|
/// related to opening the file, reading, writing, and locking.
|
||||||
|
intended_io_mode: io.ModeOverride = io.default_mode,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Upon success, the stream is in an uninitialized state. To continue using it,
|
/// Upon success, the stream is in an uninitialized state. To continue using it,
|
||||||
/// you must use the open() function.
|
/// you must use the open() function.
|
||||||
pub fn close(self: File) void {
|
pub fn close(self: File) void {
|
||||||
if (need_async_thread and self.io_mode == .blocking and !self.async_block_allowed) {
|
if (self.capable_io_mode != self.intended_io_mode) {
|
||||||
std.event.Loop.instance.?.close(self.handle);
|
std.event.Loop.instance.?.close(self.handle);
|
||||||
} else {
|
} else {
|
||||||
os.close(self.handle);
|
os.close(self.handle);
|
||||||
@ -297,11 +302,7 @@ pub const File = struct {
|
|||||||
pub const PReadError = os.PReadError;
|
pub const PReadError = os.PReadError;
|
||||||
|
|
||||||
pub fn read(self: File, buffer: []u8) ReadError!usize {
|
pub fn read(self: File, buffer: []u8) ReadError!usize {
|
||||||
if (builtin.os.tag == .windows) {
|
if (self.capable_io_mode != self.intended_io_mode) {
|
||||||
const enable_async_io = std.io.is_async and !self.async_block_allowed;
|
|
||||||
return windows.ReadFile(self.handle, buffer, null, enable_async_io);
|
|
||||||
}
|
|
||||||
if (need_async_thread and self.io_mode == .blocking and !self.async_block_allowed) {
|
|
||||||
return std.event.Loop.instance.?.read(self.handle, buffer);
|
return std.event.Loop.instance.?.read(self.handle, buffer);
|
||||||
} else {
|
} else {
|
||||||
return os.read(self.handle, buffer);
|
return os.read(self.handle, buffer);
|
||||||
@ -321,11 +322,7 @@ pub const File = struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn pread(self: File, buffer: []u8, offset: u64) PReadError!usize {
|
pub fn pread(self: File, buffer: []u8, offset: u64) PReadError!usize {
|
||||||
if (builtin.os.tag == .windows) {
|
if (self.capable_io_mode != self.intended_io_mode) {
|
||||||
const enable_async_io = std.io.is_async and !self.async_block_allowed;
|
|
||||||
return windows.ReadFile(self.handle, buffer, offset, enable_async_io);
|
|
||||||
}
|
|
||||||
if (need_async_thread and self.io_mode == .blocking and !self.async_block_allowed) {
|
|
||||||
return std.event.Loop.instance.?.pread(self.handle, buffer, offset);
|
return std.event.Loop.instance.?.pread(self.handle, buffer, offset);
|
||||||
} else {
|
} else {
|
||||||
return os.pread(self.handle, buffer, offset);
|
return os.pread(self.handle, buffer, offset);
|
||||||
@ -345,7 +342,7 @@ pub const File = struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn readv(self: File, iovecs: []const os.iovec) ReadError!usize {
|
pub fn readv(self: File, iovecs: []const os.iovec) ReadError!usize {
|
||||||
if (need_async_thread and self.io_mode == .blocking and !self.async_block_allowed) {
|
if (self.capable_io_mode != self.intended_io_mode) {
|
||||||
return std.event.Loop.instance.?.readv(self.handle, iovecs);
|
return std.event.Loop.instance.?.readv(self.handle, iovecs);
|
||||||
} else {
|
} else {
|
||||||
return os.readv(self.handle, iovecs);
|
return os.readv(self.handle, iovecs);
|
||||||
@ -379,7 +376,7 @@ pub const File = struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn preadv(self: File, iovecs: []const os.iovec, offset: u64) PReadError!usize {
|
pub fn preadv(self: File, iovecs: []const os.iovec, offset: u64) PReadError!usize {
|
||||||
if (need_async_thread and self.io_mode == .blocking and !self.async_block_allowed) {
|
if (self.capable_io_mode != self.intended_io_mode) {
|
||||||
return std.event.Loop.instance.?.preadv(self.handle, iovecs, offset);
|
return std.event.Loop.instance.?.preadv(self.handle, iovecs, offset);
|
||||||
} else {
|
} else {
|
||||||
return os.preadv(self.handle, iovecs, offset);
|
return os.preadv(self.handle, iovecs, offset);
|
||||||
@ -416,11 +413,7 @@ pub const File = struct {
|
|||||||
pub const PWriteError = os.PWriteError;
|
pub const PWriteError = os.PWriteError;
|
||||||
|
|
||||||
pub fn write(self: File, bytes: []const u8) WriteError!usize {
|
pub fn write(self: File, bytes: []const u8) WriteError!usize {
|
||||||
if (builtin.os.tag == .windows) {
|
if (self.capable_io_mode != self.intended_io_mode) {
|
||||||
const enable_async_io = std.io.is_async and !self.async_block_allowed;
|
|
||||||
return windows.WriteFile(self.handle, bytes, null, enable_async_io);
|
|
||||||
}
|
|
||||||
if (need_async_thread and self.io_mode == .blocking and !self.async_block_allowed) {
|
|
||||||
return std.event.Loop.instance.?.write(self.handle, bytes);
|
return std.event.Loop.instance.?.write(self.handle, bytes);
|
||||||
} else {
|
} else {
|
||||||
return os.write(self.handle, bytes);
|
return os.write(self.handle, bytes);
|
||||||
@ -435,11 +428,7 @@ pub const File = struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn pwrite(self: File, bytes: []const u8, offset: u64) PWriteError!usize {
|
pub fn pwrite(self: File, bytes: []const u8, offset: u64) PWriteError!usize {
|
||||||
if (builtin.os.tag == .windows) {
|
if (self.capable_io_mode != self.intended_io_mode) {
|
||||||
const enable_async_io = std.io.is_async and !self.async_block_allowed;
|
|
||||||
return windows.WriteFile(self.handle, bytes, offset, enable_async_io);
|
|
||||||
}
|
|
||||||
if (need_async_thread and self.io_mode == .blocking and !self.async_block_allowed) {
|
|
||||||
return std.event.Loop.instance.?.pwrite(self.handle, bytes, offset);
|
return std.event.Loop.instance.?.pwrite(self.handle, bytes, offset);
|
||||||
} else {
|
} else {
|
||||||
return os.pwrite(self.handle, bytes, offset);
|
return os.pwrite(self.handle, bytes, offset);
|
||||||
@ -454,7 +443,7 @@ pub const File = struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn writev(self: File, iovecs: []const os.iovec_const) WriteError!usize {
|
pub fn writev(self: File, iovecs: []const os.iovec_const) WriteError!usize {
|
||||||
if (need_async_thread and self.io_mode == .blocking and !self.async_block_allowed) {
|
if (self.capable_io_mode != self.intended_io_mode) {
|
||||||
return std.event.Loop.instance.?.writev(self.handle, iovecs);
|
return std.event.Loop.instance.?.writev(self.handle, iovecs);
|
||||||
} else {
|
} else {
|
||||||
return os.writev(self.handle, iovecs);
|
return os.writev(self.handle, iovecs);
|
||||||
@ -480,7 +469,7 @@ pub const File = struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn pwritev(self: File, iovecs: []os.iovec_const, offset: usize) PWriteError!usize {
|
pub fn pwritev(self: File, iovecs: []os.iovec_const, offset: usize) PWriteError!usize {
|
||||||
if (need_async_thread and self.io_mode == .blocking and !self.async_block_allowed) {
|
if (self.capable_io_mode != self.intended_io_mode) {
|
||||||
return std.event.Loop.instance.?.pwritev(self.handle, iovecs, offset);
|
return std.event.Loop.instance.?.pwritev(self.handle, iovecs, offset);
|
||||||
} else {
|
} else {
|
||||||
return os.pwritev(self.handle, iovecs, offset);
|
return os.pwritev(self.handle, iovecs, offset);
|
||||||
|
|||||||
@ -27,7 +27,12 @@ test "open file with exclusive nonblocking lock twice" {
|
|||||||
}
|
}
|
||||||
|
|
||||||
test "open file with lock twice, make sure it wasn't open at the same time" {
|
test "open file with lock twice, make sure it wasn't open at the same time" {
|
||||||
if (builtin.single_threaded) return;
|
if (builtin.single_threaded) return error.SkipZigTest;
|
||||||
|
|
||||||
|
if (std.io.is_async) {
|
||||||
|
// This test starts its own threads and is not compatible with async I/O.
|
||||||
|
return error.SkipZigTest;
|
||||||
|
}
|
||||||
|
|
||||||
const filename = "file_lock_test.txt";
|
const filename = "file_lock_test.txt";
|
||||||
|
|
||||||
@ -58,6 +63,11 @@ test "open file with lock twice, make sure it wasn't open at the same time" {
|
|||||||
test "create file, lock and read from multiple process at once" {
|
test "create file, lock and read from multiple process at once" {
|
||||||
if (builtin.single_threaded) return error.SkipZigTest;
|
if (builtin.single_threaded) return error.SkipZigTest;
|
||||||
|
|
||||||
|
if (std.io.is_async) {
|
||||||
|
// This test starts its own threads and is not compatible with async I/O.
|
||||||
|
return error.SkipZigTest;
|
||||||
|
}
|
||||||
|
|
||||||
if (true) {
|
if (true) {
|
||||||
// https://github.com/ziglang/zig/issues/5006
|
// https://github.com/ziglang/zig/issues/5006
|
||||||
return error.SkipZigTest;
|
return error.SkipZigTest;
|
||||||
|
|||||||
@ -30,6 +30,11 @@ else
|
|||||||
Mode.blocking;
|
Mode.blocking;
|
||||||
pub const is_async = mode != .blocking;
|
pub const is_async = mode != .blocking;
|
||||||
|
|
||||||
|
/// This is an enum value to use for I/O mode at runtime, since it takes up zero bytes at runtime,
|
||||||
|
/// and makes expressions comptime-known when `is_async` is `false`.
|
||||||
|
pub const ModeOverride = if (is_async) Mode else enum { blocking };
|
||||||
|
pub const default_mode: ModeOverride = if (is_async) Mode.evented else .blocking;
|
||||||
|
|
||||||
fn getStdOutHandle() os.fd_t {
|
fn getStdOutHandle() os.fd_t {
|
||||||
if (builtin.os.tag == .windows) {
|
if (builtin.os.tag == .windows) {
|
||||||
return os.windows.peb().ProcessParameters.hStdOutput;
|
return os.windows.peb().ProcessParameters.hStdOutput;
|
||||||
@ -42,12 +47,13 @@ fn getStdOutHandle() os.fd_t {
|
|||||||
return os.STDOUT_FILENO;
|
return os.STDOUT_FILENO;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: async stdout on windows (https://github.com/ziglang/zig/pull/4816#issuecomment-604521023)
|
/// TODO: async stdout on windows without a dedicated thread.
|
||||||
|
/// https://github.com/ziglang/zig/pull/4816#issuecomment-604521023
|
||||||
pub fn getStdOut() File {
|
pub fn getStdOut() File {
|
||||||
return File{
|
return File{
|
||||||
.handle = getStdOutHandle(),
|
.handle = getStdOutHandle(),
|
||||||
.io_mode = .blocking,
|
.capable_io_mode = .blocking,
|
||||||
.async_block_allowed = if (builtin.os.tag == .windows) File.async_block_allowed_yes else File.async_block_allowed_no,
|
.intended_io_mode = default_mode,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -63,11 +69,13 @@ fn getStdErrHandle() os.fd_t {
|
|||||||
return os.STDERR_FILENO;
|
return os.STDERR_FILENO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// This returns a `File` that is configured to block with every write, in order
|
||||||
|
/// to facilitate better debugging. This can be changed by modifying the `intended_io_mode` field.
|
||||||
pub fn getStdErr() File {
|
pub fn getStdErr() File {
|
||||||
return File{
|
return File{
|
||||||
.handle = getStdErrHandle(),
|
.handle = getStdErrHandle(),
|
||||||
.io_mode = .blocking,
|
.capable_io_mode = .blocking,
|
||||||
.async_block_allowed = File.async_block_allowed_yes,
|
.intended_io_mode = .blocking,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -83,12 +91,13 @@ fn getStdInHandle() os.fd_t {
|
|||||||
return os.STDIN_FILENO;
|
return os.STDIN_FILENO;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: async stdin on windows (https://github.com/ziglang/zig/pull/4816#issuecomment-604521023)
|
/// TODO: async stdin on windows without a dedicated thread.
|
||||||
|
/// https://github.com/ziglang/zig/pull/4816#issuecomment-604521023
|
||||||
pub fn getStdIn() File {
|
pub fn getStdIn() File {
|
||||||
return File{
|
return File{
|
||||||
.handle = getStdInHandle(),
|
.handle = getStdInHandle(),
|
||||||
.io_mode = .blocking,
|
.capable_io_mode = .blocking,
|
||||||
.async_block_allowed = if (builtin.os.tag == .windows) File.async_block_allowed_yes else File.async_block_allowed_no,
|
.intended_io_mode = default_mode,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -412,7 +412,7 @@ pub fn tcpConnectToAddress(address: Address) !fs.File {
|
|||||||
errdefer os.close(sockfd);
|
errdefer os.close(sockfd);
|
||||||
try os.connect(sockfd, &address.any, address.getOsSockLen());
|
try os.connect(sockfd, &address.any, address.getOsSockLen());
|
||||||
|
|
||||||
return fs.File{ .handle = sockfd, .io_mode = std.io.mode };
|
return fs.File{ .handle = sockfd };
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Call `AddressList.deinit` on the result.
|
/// Call `AddressList.deinit` on the result.
|
||||||
@ -1381,10 +1381,7 @@ pub const StreamServer = struct {
|
|||||||
var adr_len: os.socklen_t = @sizeOf(Address);
|
var adr_len: os.socklen_t = @sizeOf(Address);
|
||||||
if (os.accept4(self.sockfd.?, &accepted_addr.any, &adr_len, accept_flags)) |fd| {
|
if (os.accept4(self.sockfd.?, &accepted_addr.any, &adr_len, accept_flags)) |fd| {
|
||||||
return Connection{
|
return Connection{
|
||||||
.file = fs.File{
|
.file = fs.File{ .handle = fd },
|
||||||
.handle = fd,
|
|
||||||
.io_mode = std.io.mode,
|
|
||||||
},
|
|
||||||
.address = accepted_addr,
|
.address = accepted_addr,
|
||||||
};
|
};
|
||||||
} else |err| switch (err) {
|
} else |err| switch (err) {
|
||||||
|
|||||||
@ -173,8 +173,8 @@ fn getRandomBytesDevURandom(buf: []u8) !void {
|
|||||||
|
|
||||||
const file = std.fs.File{
|
const file = std.fs.File{
|
||||||
.handle = fd,
|
.handle = fd,
|
||||||
.io_mode = .blocking,
|
.capable_io_mode = .blocking,
|
||||||
.async_block_allowed = std.fs.File.async_block_allowed_yes,
|
.intended_io_mode = .blocking,
|
||||||
};
|
};
|
||||||
const stream = file.inStream();
|
const stream = file.inStream();
|
||||||
stream.readNoEof(buf) catch return error.Unexpected;
|
stream.readNoEof(buf) catch return error.Unexpected;
|
||||||
@ -305,7 +305,7 @@ pub const ReadError = error{
|
|||||||
/// For POSIX the limit is `math.maxInt(isize)`.
|
/// For POSIX the limit is `math.maxInt(isize)`.
|
||||||
pub fn read(fd: fd_t, buf: []u8) ReadError!usize {
|
pub fn read(fd: fd_t, buf: []u8) ReadError!usize {
|
||||||
if (builtin.os.tag == .windows) {
|
if (builtin.os.tag == .windows) {
|
||||||
return windows.ReadFile(fd, buf, null, false);
|
return windows.ReadFile(fd, buf, null, std.io.default_mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (builtin.os.tag == .wasi and !builtin.link_libc) {
|
if (builtin.os.tag == .wasi and !builtin.link_libc) {
|
||||||
@ -408,7 +408,7 @@ pub const PReadError = ReadError || error{Unseekable};
|
|||||||
/// used to perform the I/O. `error.WouldBlock` is not possible on Windows.
|
/// used to perform the I/O. `error.WouldBlock` is not possible on Windows.
|
||||||
pub fn pread(fd: fd_t, buf: []u8, offset: u64) PReadError!usize {
|
pub fn pread(fd: fd_t, buf: []u8, offset: u64) PReadError!usize {
|
||||||
if (builtin.os.tag == .windows) {
|
if (builtin.os.tag == .windows) {
|
||||||
return windows.ReadFile(fd, buf, offset, false);
|
return windows.ReadFile(fd, buf, offset, std.io.default_mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
@ -584,7 +584,7 @@ pub const WriteError = error{
|
|||||||
/// The corresponding POSIX limit is `math.maxInt(isize)`.
|
/// The corresponding POSIX limit is `math.maxInt(isize)`.
|
||||||
pub fn write(fd: fd_t, bytes: []const u8) WriteError!usize {
|
pub fn write(fd: fd_t, bytes: []const u8) WriteError!usize {
|
||||||
if (builtin.os.tag == .windows) {
|
if (builtin.os.tag == .windows) {
|
||||||
return windows.WriteFile(fd, bytes, null, false);
|
return windows.WriteFile(fd, bytes, null, std.io.default_mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (builtin.os.tag == .wasi and !builtin.link_libc) {
|
if (builtin.os.tag == .wasi and !builtin.link_libc) {
|
||||||
@ -709,7 +709,7 @@ pub const PWriteError = WriteError || error{Unseekable};
|
|||||||
/// The corresponding POSIX limit is `math.maxInt(isize)`.
|
/// The corresponding POSIX limit is `math.maxInt(isize)`.
|
||||||
pub fn pwrite(fd: fd_t, bytes: []const u8, offset: u64) PWriteError!usize {
|
pub fn pwrite(fd: fd_t, bytes: []const u8, offset: u64) PWriteError!usize {
|
||||||
if (std.Target.current.os.tag == .windows) {
|
if (std.Target.current.os.tag == .windows) {
|
||||||
return windows.WriteFile(fd, bytes, offset, false);
|
return windows.WriteFile(fd, bytes, offset, std.io.default_mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prevent EINVAL.
|
// Prevent EINVAL.
|
||||||
|
|||||||
@ -110,7 +110,7 @@ pub const OpenFileOptions = struct {
|
|||||||
share_access: ULONG = FILE_SHARE_WRITE | FILE_SHARE_READ | FILE_SHARE_DELETE,
|
share_access: ULONG = FILE_SHARE_WRITE | FILE_SHARE_READ | FILE_SHARE_DELETE,
|
||||||
share_access_nonblocking: bool = false,
|
share_access_nonblocking: bool = false,
|
||||||
creation: ULONG,
|
creation: ULONG,
|
||||||
enable_async_io: bool = std.io.is_async,
|
io_mode: std.io.ModeOverride,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// TODO when share_access_nonblocking is false, this implementation uses
|
/// TODO when share_access_nonblocking is false, this implementation uses
|
||||||
@ -145,7 +145,7 @@ pub fn OpenFile(sub_path_w: []const u16, options: OpenFileOptions) OpenError!HAN
|
|||||||
|
|
||||||
var delay: usize = 1;
|
var delay: usize = 1;
|
||||||
while (true) {
|
while (true) {
|
||||||
const blocking_flag: ULONG = if (!options.enable_async_io) FILE_SYNCHRONOUS_IO_NONALERT else 0;
|
const blocking_flag: ULONG = if (options.io_mode == .blocking) FILE_SYNCHRONOUS_IO_NONALERT else 0;
|
||||||
const rc = ntdll.NtCreateFile(
|
const rc = ntdll.NtCreateFile(
|
||||||
&result,
|
&result,
|
||||||
options.access_mask,
|
options.access_mask,
|
||||||
@ -451,11 +451,11 @@ pub const ReadFileError = error{
|
|||||||
|
|
||||||
/// If buffer's length exceeds what a Windows DWORD integer can hold, it will be broken into
|
/// If buffer's length exceeds what a Windows DWORD integer can hold, it will be broken into
|
||||||
/// multiple non-atomic reads.
|
/// multiple non-atomic reads.
|
||||||
pub fn ReadFile(in_hFile: HANDLE, buffer: []u8, offset: ?u64, enable_async_io: bool) ReadFileError!usize {
|
pub fn ReadFile(in_hFile: HANDLE, buffer: []u8, offset: ?u64, io_mode: std.io.ModeOverride) ReadFileError!usize {
|
||||||
if (std.event.Loop.instance != null and enable_async_io) {
|
if (io_mode != .blocking) {
|
||||||
const loop = std.event.Loop.instance.?;
|
const loop = std.event.Loop.instance.?;
|
||||||
// TODO support async ReadFile with no offset
|
// TODO make getting the file position non-blocking
|
||||||
const off = if (offset == null) 0 else offset.?;
|
const off = if (offset) |o| o else try SetFilePointerEx_CURRENT_get(in_hFile);
|
||||||
var resume_node = std.event.Loop.ResumeNode.Basic{
|
var resume_node = std.event.Loop.ResumeNode.Basic{
|
||||||
.base = .{
|
.base = .{
|
||||||
.id = .Basic,
|
.id = .Basic,
|
||||||
@ -486,6 +486,11 @@ pub fn ReadFile(in_hFile: HANDLE, buffer: []u8, offset: ?u64, enable_async_io: b
|
|||||||
else => |err| return unexpectedError(err),
|
else => |err| return unexpectedError(err),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (offset == null) {
|
||||||
|
// TODO make setting the file position non-blocking
|
||||||
|
const new_off = off + bytes_transferred;
|
||||||
|
try SetFilePointerEx_CURRENT(in_hFile, @bitCast(i64, new_off));
|
||||||
|
}
|
||||||
return @as(usize, bytes_transferred);
|
return @as(usize, bytes_transferred);
|
||||||
} else {
|
} else {
|
||||||
var index: usize = 0;
|
var index: usize = 0;
|
||||||
@ -525,11 +530,16 @@ pub const WriteFileError = error{
|
|||||||
Unexpected,
|
Unexpected,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn WriteFile(handle: HANDLE, bytes: []const u8, offset: ?u64, enable_async_io: bool) WriteFileError!usize {
|
pub fn WriteFile(
|
||||||
if (std.event.Loop.instance != null and enable_async_io) {
|
handle: HANDLE,
|
||||||
|
bytes: []const u8,
|
||||||
|
offset: ?u64,
|
||||||
|
io_mode: std.io.ModeOverride,
|
||||||
|
) WriteFileError!usize {
|
||||||
|
if (std.event.Loop.instance != null and io_mode != .blocking) {
|
||||||
const loop = std.event.Loop.instance.?;
|
const loop = std.event.Loop.instance.?;
|
||||||
// TODO support async WriteFile with no offset
|
// TODO make getting the file position non-blocking
|
||||||
const off = if (offset == null) 0 else offset.?;
|
const off = if (offset) |o| o else try SetFilePointerEx_CURRENT_get(handle);
|
||||||
var resume_node = std.event.Loop.ResumeNode.Basic{
|
var resume_node = std.event.Loop.ResumeNode.Basic{
|
||||||
.base = .{
|
.base = .{
|
||||||
.id = .Basic,
|
.id = .Basic,
|
||||||
@ -562,6 +572,11 @@ pub fn WriteFile(handle: HANDLE, bytes: []const u8, offset: ?u64, enable_async_i
|
|||||||
else => |err| return unexpectedError(err),
|
else => |err| return unexpectedError(err),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (offset == null) {
|
||||||
|
// TODO make setting the file position non-blocking
|
||||||
|
const new_off = off + bytes_transferred;
|
||||||
|
try SetFilePointerEx_CURRENT(handle, @bitCast(i64, new_off));
|
||||||
|
}
|
||||||
return bytes_transferred;
|
return bytes_transferred;
|
||||||
} else {
|
} else {
|
||||||
var bytes_written: DWORD = undefined;
|
var bytes_written: DWORD = undefined;
|
||||||
|
|||||||
@ -470,7 +470,7 @@ pub const Pdb = struct {
|
|||||||
msf: Msf,
|
msf: Msf,
|
||||||
|
|
||||||
pub fn openFile(self: *Pdb, coff_ptr: *coff.Coff, file_name: []u8) !void {
|
pub fn openFile(self: *Pdb, coff_ptr: *coff.Coff, file_name: []u8) !void {
|
||||||
self.in_file = try fs.cwd().openFile(file_name, .{ .always_blocking = true });
|
self.in_file = try fs.cwd().openFile(file_name, .{ .intended_io_mode = .blocking });
|
||||||
self.allocator = coff_ptr.allocator;
|
self.allocator = coff_ptr.allocator;
|
||||||
self.coff = coff_ptr;
|
self.coff = coff_ptr;
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user