| author | |
| committer | |
| log | 3b515fbede945a2927d5aba59212553a8b26b944 |
| tree | 76f7583b67d1e817efb0d2f401836d9a229aaf83 |
| parent | 6be202f46633d02e20d0f068a32296113ecb95ca |
| parent | 80625990d5ce82b781de54c4587b489cbd2cd55f |
Reviewed-on: https://codeberg.org/ziglang/zig/pulls/3108945 files changed, 517 insertions(+), 487 deletions(-)
lib/compiler/test_runner.zig+1-1| ... | ... | @@ -17,7 +17,7 @@ var fba: std.heap.FixedBufferAllocator = .init(&fba_buffer); |
| 17 | 17 | var fba_buffer: [8192]u8 = undefined; |
| 18 | 18 | var stdin_buffer: [4096]u8 = undefined; |
| 19 | 19 | var stdout_buffer: [4096]u8 = undefined; |
| 20 | const runner_threaded_io: Io = Io.Threaded.global_single_threaded.ioBasic(); | |
| 20 | const runner_threaded_io: Io = Io.Threaded.global_single_threaded.io(); | |
| 21 | 21 | |
| 22 | 22 | /// Keep in sync with logic in `std.Build.addRunArtifact` which decides whether |
| 23 | 23 | /// the test runner will communicate with the build runner via `std.zig.Server`. |
lib/compiler_rt.zig+1-1| ... | ... | @@ -17,7 +17,7 @@ else |
| 17 | 17 | null; |
| 18 | 18 | |
| 19 | 19 | pub const std_options_debug_io: std.Io = if (builtin.is_test) |
| 20 | std.Io.Threaded.global_single_threaded.ioBasic() | |
| 20 | std.Io.Threaded.global_single_threaded.io() | |
| 21 | 21 | else |
| 22 | 22 | unreachable; |
| 23 | 23 |
lib/fuzzer.zig+1-1| ... | ... | @@ -13,7 +13,7 @@ pub const std_options = std.Options{ |
| 13 | 13 | .logFn = logOverride, |
| 14 | 14 | }; |
| 15 | 15 | |
| 16 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | |
| 16 | const io = std.Io.Threaded.global_single_threaded.io(); | |
| 17 | 17 | |
| 18 | 18 | fn logOverride( |
| 19 | 19 | comptime level: std.log.Level, |
lib/std/Io.zig+44-2| ... | ... | @@ -243,7 +243,6 @@ pub const VTable = struct { |
| 243 | 243 | netConnectUnix: *const fn (?*anyopaque, *const net.UnixAddress) net.UnixAddress.ConnectError!net.Socket.Handle, |
| 244 | 244 | netSocketCreatePair: *const fn (?*anyopaque, net.Socket.CreatePairOptions) net.Socket.CreatePairError![2]net.Socket, |
| 245 | 245 | netSend: *const fn (?*anyopaque, net.Socket.Handle, []net.OutgoingMessage, net.SendFlags) struct { ?net.Socket.SendError, usize }, |
| 246 | netReceive: *const fn (?*anyopaque, net.Socket.Handle, message_buffer: []net.IncomingMessage, data_buffer: []u8, net.ReceiveFlags, Timeout) struct { ?net.Socket.ReceiveTimeoutError, usize }, | |
| 247 | 246 | /// Returns 0 on end of stream. |
| 248 | 247 | netRead: *const fn (?*anyopaque, src: net.Socket.Handle, data: [][]u8) net.Stream.Reader.Error!usize, |
| 249 | 248 | netWrite: *const fn (?*anyopaque, dest: net.Socket.Handle, header: []const u8, data: []const []const u8, splat: usize) net.Stream.Writer.Error!usize, |
| ... | ... | @@ -261,6 +260,7 @@ pub const Operation = union(enum) { |
| 261 | 260 | /// On Windows this is NtDeviceIoControlFile. On POSIX this is ioctl. On |
| 262 | 261 | /// other systems this tag is unreachable. |
| 263 | 262 | device_io_control: DeviceIoControl, |
| 263 | net_receive: NetReceive, | |
| 264 | 264 | |
| 265 | 265 | pub const Tag = @typeInfo(Operation).@"union".tag_type.?; |
| 266 | 266 | |
| ... | ... | @@ -350,6 +350,35 @@ pub const Operation = union(enum) { |
| 350 | 350 | }, |
| 351 | 351 | }; |
| 352 | 352 | |
| 353 | pub const NetReceive = struct { | |
| 354 | socket_handle: net.Socket.Handle, | |
| 355 | message_buffer: []net.IncomingMessage, | |
| 356 | data_buffer: []u8, | |
| 357 | flags: net.ReceiveFlags, | |
| 358 | ||
| 359 | pub const Error = error{ | |
| 360 | /// Insufficient memory or other resource internal to the operating system. | |
| 361 | SystemResources, | |
| 362 | /// Per-process limit on the number of open file descriptors has been reached. | |
| 363 | ProcessFdQuotaExceeded, | |
| 364 | /// System-wide limit on the total number of open files has been reached. | |
| 365 | SystemFdQuotaExceeded, | |
| 366 | /// Local end has been shut down on a connection-oriented socket, or | |
| 367 | /// the socket was never connected. | |
| 368 | SocketUnconnected, | |
| 369 | /// The socket type requires that message be sent atomically, and the | |
| 370 | /// size of the message to be sent made this impossible. The message | |
| 371 | /// was not transmitted, or was partially transmitted. | |
| 372 | MessageOversize, | |
| 373 | /// Network connection was unexpectedly closed by sender. | |
| 374 | ConnectionResetByPeer, | |
| 375 | /// The local network interface used to reach the destination is offline. | |
| 376 | NetworkDown, | |
| 377 | } || Io.UnexpectedError; | |
| 378 | ||
| 379 | pub const Result = struct { ?net.Socket.ReceiveError, usize }; | |
| 380 | }; | |
| 381 | ||
| 353 | 382 | pub const Result = Result: { |
| 354 | 383 | const operation_fields = @typeInfo(Operation).@"union".fields; |
| 355 | 384 | var field_names: [operation_fields.len][]const u8 = undefined; |
| ... | ... | @@ -417,6 +446,19 @@ pub fn operate(io: Io, operation: Operation) Cancelable!Operation.Result { |
| 417 | 446 | return io.vtable.operate(io.userdata, operation); |
| 418 | 447 | } |
| 419 | 448 | |
| 449 | pub const OperateTimeoutError = Cancelable || Timeout.Error || ConcurrentError; | |
| 450 | ||
| 451 | /// Performs one `Operation` with provided `timeout`. | |
| 452 | pub fn operateTimeout(io: Io, operation: Operation, timeout: Timeout) OperateTimeoutError!Operation.Result { | |
| 453 | var storage: [1]Operation.Storage = undefined; | |
| 454 | var batch: Batch = .init(&storage); | |
| 455 | batch.addAt(0, operation); | |
| 456 | try batch.awaitConcurrent(io, timeout); | |
| 457 | const completion = batch.next().?; | |
| 458 | assert(completion.index == 0); | |
| 459 | return completion.result; | |
| 460 | } | |
| 461 | ||
| 420 | 462 | /// Submits many operations together without waiting for all of them to |
| 421 | 463 | /// complete. |
| 422 | 464 | /// |
| ... | ... | @@ -1716,7 +1758,7 @@ pub const Event = enum(u32) { |
| 1716 | 1758 | } |
| 1717 | 1759 | |
| 1718 | 1760 | /// Blocks until the logical boolean is `true`. |
| 1719 | pub fn wait(event: *Event, io: Io) Io.Cancelable!void { | |
| 1761 | pub fn wait(event: *Event, io: Io) Cancelable!void { | |
| 1720 | 1762 | if (@cmpxchgStrong(Event, event, .unset, .waiting, .acquire, .acquire)) |prev| switch (prev) { |
| 1721 | 1763 | .unset => unreachable, |
| 1722 | 1764 | .waiting => {}, |
lib/std/Io/Dispatch.zig+3-19| ... | ... | @@ -459,7 +459,6 @@ pub fn io(ev: *Evented) Io { |
| 459 | 459 | .netConnectUnix = netConnectUnixUnavailable, |
| 460 | 460 | .netSocketCreatePair = netSocketCreatePairUnavailable, |
| 461 | 461 | .netSend = netSendUnavailable, |
| 462 | .netReceive = netReceiveUnavailable, | |
| 463 | 462 | .netRead = netReadUnavailable, |
| 464 | 463 | .netWrite = netWriteUnavailable, |
| 465 | 464 | .netWriteFile = netWriteFileUnavailable, |
| ... | ... | @@ -1714,6 +1713,7 @@ fn operate(userdata: ?*anyopaque, operation: Io.Operation) Io.Cancelable!Io.Oper |
| 1714 | 1713 | }, |
| 1715 | 1714 | }, |
| 1716 | 1715 | .device_io_control => |*o| return .{ .device_io_control = try deviceIoControl(o) }, |
| 1716 | .net_receive => @panic("TODO implement net_receive operation"), | |
| 1717 | 1717 | } |
| 1718 | 1718 | } |
| 1719 | 1719 | |
| ... | ... | @@ -2134,6 +2134,7 @@ fn batchDrainSubmitted( |
| 2134 | 2134 | break :result null; |
| 2135 | 2135 | }, |
| 2136 | 2136 | .device_io_control => {}, |
| 2137 | .net_receive => @panic("TODO implement batched net_receive"), | |
| 2137 | 2138 | }; |
| 2138 | 2139 | if (concurrency) return error.ConcurrencyUnavailable; |
| 2139 | 2140 | break :result try operate(ev, storage.submission.operation); |
| ... | ... | @@ -2192,6 +2193,7 @@ fn batchSourceEvent(context: ?*anyopaque) callconv(.c) void { |
| 2192 | 2193 | } }; |
| 2193 | 2194 | }, |
| 2194 | 2195 | .device_io_control => unreachable, |
| 2196 | .net_receive => @panic("TODO implement batched net_receive"), | |
| 2195 | 2197 | }; |
| 2196 | 2198 | |
| 2197 | 2199 | switch (pending.node.prev) { |
| ... | ... | @@ -4872,24 +4874,6 @@ fn netSendUnavailable( |
| 4872 | 4874 | return .{ error.NetworkDown, 0 }; |
| 4873 | 4875 | } |
| 4874 | 4876 | |
| 4875 | fn netReceiveUnavailable( | |
| 4876 | userdata: ?*anyopaque, | |
| 4877 | handle: net.Socket.Handle, | |
| 4878 | message_buffer: []net.IncomingMessage, | |
| 4879 | data_buffer: []u8, | |
| 4880 | flags: net.ReceiveFlags, | |
| 4881 | timeout: Io.Timeout, | |
| 4882 | ) struct { ?net.Socket.ReceiveTimeoutError, usize } { | |
| 4883 | const ev: *Evented = @ptrCast(@alignCast(userdata)); | |
| 4884 | _ = ev; | |
| 4885 | _ = handle; | |
| 4886 | _ = message_buffer; | |
| 4887 | _ = data_buffer; | |
| 4888 | _ = flags; | |
| 4889 | _ = timeout; | |
| 4890 | return .{ error.NetworkDown, 0 }; | |
| 4891 | } | |
| 4892 | ||
| 4893 | 4877 | fn netReadUnavailable( |
| 4894 | 4878 | userdata: ?*anyopaque, |
| 4895 | 4879 | fd: net.Socket.Handle, |
lib/std/Io/Threaded.zig+309-295| ... | ... | @@ -61,7 +61,7 @@ disable_memory_mapping: bool, |
| 61 | 61 | |
| 62 | 62 | stderr_writer: File.Writer = .{ |
| 63 | 63 | .io = undefined, |
| 64 | .interface = Io.File.Writer.initInterface(&.{}), | |
| 64 | .interface = File.Writer.initInterface(&.{}), | |
| 65 | 65 | .file = if (is_windows) undefined else .stderr(), |
| 66 | 66 | .mode = .streaming, |
| 67 | 67 | }, |
| ... | ... | @@ -160,7 +160,7 @@ pub const Environ = struct { |
| 160 | 160 | }, |
| 161 | 161 | }; |
| 162 | 162 | |
| 163 | pub fn scan(environ: *Environ, allocator: std.mem.Allocator) void { | |
| 163 | pub fn scan(environ: *Environ, allocator: Allocator) void { | |
| 164 | 164 | if (is_windows) { |
| 165 | 165 | // This value expires with any call that modifies the environment, |
| 166 | 166 | // which is outside of this Io implementation's control, so references |
| ... | ... | @@ -1901,10 +1901,6 @@ pub fn io(t: *Threaded) Io { |
| 1901 | 1901 | .windows => netSendWindows, |
| 1902 | 1902 | else => netSendPosix, |
| 1903 | 1903 | }, |
| 1904 | .netReceive = switch (native_os) { | |
| 1905 | .windows => netReceiveWindows, | |
| 1906 | else => netReceivePosix, | |
| 1907 | }, | |
| 1908 | 1904 | .netInterfaceNameResolve = netInterfaceNameResolve, |
| 1909 | 1905 | .netInterfaceName = netInterfaceName, |
| 1910 | 1906 | .netLookup = netLookup, |
| ... | ... | @@ -1912,143 +1908,10 @@ pub fn io(t: *Threaded) Io { |
| 1912 | 1908 | }; |
| 1913 | 1909 | } |
| 1914 | 1910 | |
| 1915 | /// Same as `io` but disables all networking functionality, which has | |
| 1916 | /// an additional dependency on Windows (ws2_32). | |
| 1917 | pub fn ioBasic(t: *Threaded) Io { | |
| 1918 | return .{ | |
| 1919 | .userdata = t, | |
| 1920 | .vtable = &.{ | |
| 1921 | .crashHandler = crashHandler, | |
| 1922 | ||
| 1923 | .async = async, | |
| 1924 | .concurrent = concurrent, | |
| 1925 | .await = await, | |
| 1926 | .cancel = cancel, | |
| 1927 | ||
| 1928 | .groupAsync = groupAsync, | |
| 1929 | .groupConcurrent = groupConcurrent, | |
| 1930 | .groupAwait = groupAwait, | |
| 1931 | .groupCancel = groupCancel, | |
| 1932 | ||
| 1933 | .recancel = recancel, | |
| 1934 | .swapCancelProtection = swapCancelProtection, | |
| 1935 | .checkCancel = checkCancel, | |
| 1936 | ||
| 1937 | .futexWait = futexWait, | |
| 1938 | .futexWaitUncancelable = futexWaitUncancelable, | |
| 1939 | .futexWake = futexWake, | |
| 1940 | ||
| 1941 | .operate = operate, | |
| 1942 | .batchAwaitAsync = batchAwaitAsync, | |
| 1943 | .batchAwaitConcurrent = batchAwaitConcurrent, | |
| 1944 | .batchCancel = batchCancel, | |
| 1945 | ||
| 1946 | .dirCreateDir = dirCreateDir, | |
| 1947 | .dirCreateDirPath = dirCreateDirPath, | |
| 1948 | .dirCreateDirPathOpen = dirCreateDirPathOpen, | |
| 1949 | .dirStat = dirStat, | |
| 1950 | .dirStatFile = dirStatFile, | |
| 1951 | .dirAccess = dirAccess, | |
| 1952 | .dirCreateFile = dirCreateFile, | |
| 1953 | .dirCreateFileAtomic = dirCreateFileAtomic, | |
| 1954 | .dirOpenFile = dirOpenFile, | |
| 1955 | .dirOpenDir = dirOpenDir, | |
| 1956 | .dirClose = dirClose, | |
| 1957 | .dirRead = dirRead, | |
| 1958 | .dirRealPath = dirRealPath, | |
| 1959 | .dirRealPathFile = dirRealPathFile, | |
| 1960 | .dirDeleteFile = dirDeleteFile, | |
| 1961 | .dirDeleteDir = dirDeleteDir, | |
| 1962 | .dirRename = dirRename, | |
| 1963 | .dirRenamePreserve = dirRenamePreserve, | |
| 1964 | .dirSymLink = dirSymLink, | |
| 1965 | .dirReadLink = dirReadLink, | |
| 1966 | .dirSetOwner = dirSetOwner, | |
| 1967 | .dirSetFileOwner = dirSetFileOwner, | |
| 1968 | .dirSetPermissions = dirSetPermissions, | |
| 1969 | .dirSetFilePermissions = dirSetFilePermissions, | |
| 1970 | .dirSetTimestamps = dirSetTimestamps, | |
| 1971 | .dirHardLink = dirHardLink, | |
| 1972 | ||
| 1973 | .fileStat = fileStat, | |
| 1974 | .fileLength = fileLength, | |
| 1975 | .fileClose = fileClose, | |
| 1976 | .fileWritePositional = fileWritePositional, | |
| 1977 | .fileWriteFileStreaming = fileWriteFileStreaming, | |
| 1978 | .fileWriteFilePositional = fileWriteFilePositional, | |
| 1979 | .fileReadPositional = fileReadPositional, | |
| 1980 | .fileSeekBy = fileSeekBy, | |
| 1981 | .fileSeekTo = fileSeekTo, | |
| 1982 | .fileSync = fileSync, | |
| 1983 | .fileIsTty = fileIsTty, | |
| 1984 | .fileEnableAnsiEscapeCodes = fileEnableAnsiEscapeCodes, | |
| 1985 | .fileSupportsAnsiEscapeCodes = fileSupportsAnsiEscapeCodes, | |
| 1986 | .fileSetLength = fileSetLength, | |
| 1987 | .fileSetOwner = fileSetOwner, | |
| 1988 | .fileSetPermissions = fileSetPermissions, | |
| 1989 | .fileSetTimestamps = fileSetTimestamps, | |
| 1990 | .fileLock = fileLock, | |
| 1991 | .fileTryLock = fileTryLock, | |
| 1992 | .fileUnlock = fileUnlock, | |
| 1993 | .fileDowngradeLock = fileDowngradeLock, | |
| 1994 | .fileRealPath = fileRealPath, | |
| 1995 | .fileHardLink = fileHardLink, | |
| 1996 | ||
| 1997 | .fileMemoryMapCreate = fileMemoryMapCreate, | |
| 1998 | .fileMemoryMapDestroy = fileMemoryMapDestroy, | |
| 1999 | .fileMemoryMapSetLength = fileMemoryMapSetLength, | |
| 2000 | .fileMemoryMapRead = fileMemoryMapRead, | |
| 2001 | .fileMemoryMapWrite = fileMemoryMapWrite, | |
| 2002 | ||
| 2003 | .processExecutableOpen = processExecutableOpen, | |
| 2004 | .processExecutablePath = processExecutablePath, | |
| 2005 | .lockStderr = lockStderr, | |
| 2006 | .tryLockStderr = tryLockStderr, | |
| 2007 | .unlockStderr = unlockStderr, | |
| 2008 | .processCurrentPath = processCurrentPath, | |
| 2009 | .processSetCurrentDir = processSetCurrentDir, | |
| 2010 | .processSetCurrentPath = processSetCurrentPath, | |
| 2011 | .processReplace = processReplace, | |
| 2012 | .processReplacePath = processReplacePath, | |
| 2013 | .processSpawn = processSpawn, | |
| 2014 | .processSpawnPath = processSpawnPath, | |
| 2015 | .childWait = childWait, | |
| 2016 | .childKill = childKill, | |
| 2017 | ||
| 2018 | .progressParentFile = progressParentFile, | |
| 2019 | ||
| 2020 | .now = now, | |
| 2021 | .clockResolution = clockResolution, | |
| 2022 | .sleep = sleep, | |
| 2023 | ||
| 2024 | .random = random, | |
| 2025 | .randomSecure = randomSecure, | |
| 2026 | ||
| 2027 | .netListenIp = netListenIpUnavailable, | |
| 2028 | .netListenUnix = netListenUnixUnavailable, | |
| 2029 | .netAccept = netAcceptUnavailable, | |
| 2030 | .netBindIp = netBindIpUnavailable, | |
| 2031 | .netConnectIp = netConnectIpUnavailable, | |
| 2032 | .netSocketCreatePair = netSocketCreatePairUnavailable, | |
| 2033 | .netConnectUnix = netConnectUnixUnavailable, | |
| 2034 | .netClose = netCloseUnavailable, | |
| 2035 | .netShutdown = netShutdownUnavailable, | |
| 2036 | .netRead = netReadUnavailable, | |
| 2037 | .netWrite = netWriteUnavailable, | |
| 2038 | .netWriteFile = netWriteFileUnavailable, | |
| 2039 | .netSend = netSendUnavailable, | |
| 2040 | .netReceive = netReceiveUnavailable, | |
| 2041 | .netInterfaceNameResolve = netInterfaceNameResolveUnavailable, | |
| 2042 | .netInterfaceName = netInterfaceNameUnavailable, | |
| 2043 | .netLookup = netLookupUnavailable, | |
| 2044 | }, | |
| 2045 | }; | |
| 2046 | } | |
| 2047 | ||
| 2048 | 1911 | pub const socket_flags_unsupported = is_darwin or native_os == .haiku; |
| 2049 | 1912 | const have_accept4 = !socket_flags_unsupported; |
| 2050 | 1913 | const have_flock_open_flags = @hasField(posix.O, "EXLOCK"); |
| 2051 | const have_networking = native_os != .wasi; | |
| 1914 | const have_networking = std.options.networking and native_os != .wasi; | |
| 2052 | 1915 | const have_flock = @TypeOf(posix.system.flock) != void; |
| 2053 | 1916 | const have_sendmmsg = native_os == .linux; |
| 2054 | 1917 | const have_futex = switch (builtin.cpu.arch) { |
| ... | ... | @@ -2600,7 +2463,7 @@ fn futexWait(userdata: ?*anyopaque, ptr: *const u32, expected: u32, timeout: Io. |
| 2600 | 2463 | return; |
| 2601 | 2464 | } |
| 2602 | 2465 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| 2603 | const t_io = ioBasic(t); | |
| 2466 | const t_io = io(t); | |
| 2604 | 2467 | const timeout_ns: ?u64 = ns: { |
| 2605 | 2468 | const d = timeout.toDurationFromNow(t_io) orelse break :ns null; |
| 2606 | 2469 | break :ns std.math.lossyCast(u64, d.raw.toNanoseconds()); |
| ... | ... | @@ -2638,13 +2501,23 @@ fn operate(userdata: ?*anyopaque, operation: Io.Operation) Io.Cancelable!Io.Oper |
| 2638 | 2501 | }, |
| 2639 | 2502 | }, |
| 2640 | 2503 | .device_io_control => |*o| return .{ .device_io_control = try deviceIoControl(o) }, |
| 2504 | .net_receive => |*o| return .{ .net_receive = o: { | |
| 2505 | if (!have_networking) break :o .{ error.NetworkDown, 0 }; | |
| 2506 | if (is_windows) break :o netReceiveWindows(t, o.socket_handle, o.message_buffer, o.data_buffer, o.flags); | |
| 2507 | netReceivePosix(o.socket_handle, &o.message_buffer[0], o.data_buffer, o.flags, false) catch |err| switch (err) { | |
| 2508 | error.Canceled => |e| return e, | |
| 2509 | error.WouldBlock => unreachable, | |
| 2510 | else => |e| break :o .{ e, 0 }, | |
| 2511 | }; | |
| 2512 | break :o .{ null, 1 }; | |
| 2513 | } }, | |
| 2641 | 2514 | } |
| 2642 | 2515 | } |
| 2643 | 2516 | |
| 2644 | 2517 | fn batchAwaitAsync(userdata: ?*anyopaque, b: *Io.Batch) Io.Cancelable!void { |
| 2645 | 2518 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| 2646 | 2519 | if (is_windows) { |
| 2647 | batchDrainSubmittedWindows(b, false) catch |err| switch (err) { | |
| 2520 | batchDrainSubmittedWindows(t, b, false) catch |err| switch (err) { | |
| 2648 | 2521 | error.ConcurrencyUnavailable => unreachable, // passed concurrency=false |
| 2649 | 2522 | else => |e| return e, |
| 2650 | 2523 | }; |
| ... | ... | @@ -2662,11 +2535,19 @@ fn batchAwaitAsync(userdata: ?*anyopaque, b: *Io.Batch) Io.Cancelable!void { |
| 2662 | 2535 | const submission = &b.storage[index.toIndex()].submission; |
| 2663 | 2536 | switch (submission.operation) { |
| 2664 | 2537 | .file_read_streaming => |o| { |
| 2665 | poll_buffer[poll_len] = .{ .fd = o.file.handle, .events = posix.POLL.IN, .revents = 0 }; | |
| 2538 | poll_buffer[poll_len] = .{ | |
| 2539 | .fd = o.file.handle, | |
| 2540 | .events = posix.POLL.IN | posix.POLL.ERR, | |
| 2541 | .revents = 0, | |
| 2542 | }; | |
| 2666 | 2543 | poll_len += 1; |
| 2667 | 2544 | }, |
| 2668 | 2545 | .file_write_streaming => |o| { |
| 2669 | poll_buffer[poll_len] = .{ .fd = o.file.handle, .events = posix.POLL.OUT, .revents = 0 }; | |
| 2546 | poll_buffer[poll_len] = .{ | |
| 2547 | .fd = o.file.handle, | |
| 2548 | .events = posix.POLL.OUT | posix.POLL.ERR, | |
| 2549 | .revents = 0, | |
| 2550 | }; | |
| 2670 | 2551 | poll_len += 1; |
| 2671 | 2552 | }, |
| 2672 | 2553 | .device_io_control => |o| { |
| ... | ... | @@ -2677,6 +2558,14 @@ fn batchAwaitAsync(userdata: ?*anyopaque, b: *Io.Batch) Io.Cancelable!void { |
| 2677 | 2558 | }; |
| 2678 | 2559 | poll_len += 1; |
| 2679 | 2560 | }, |
| 2561 | .net_receive => |*o| { | |
| 2562 | poll_buffer[poll_len] = .{ | |
| 2563 | .fd = o.socket_handle, | |
| 2564 | .events = posix.POLL.IN | posix.POLL.ERR, | |
| 2565 | .revents = 0, | |
| 2566 | }; | |
| 2567 | poll_len += 1; | |
| 2568 | }, | |
| 2680 | 2569 | } |
| 2681 | 2570 | index = submission.node.next; |
| 2682 | 2571 | } |
| ... | ... | @@ -2767,8 +2656,8 @@ fn batchAwaitAsync(userdata: ?*anyopaque, b: *Io.Batch) Io.Cancelable!void { |
| 2767 | 2656 | fn batchAwaitConcurrent(userdata: ?*anyopaque, b: *Io.Batch, timeout: Io.Timeout) Io.Batch.AwaitConcurrentError!void { |
| 2768 | 2657 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| 2769 | 2658 | if (is_windows) { |
| 2770 | const deadline: ?Io.Clock.Timestamp = timeout.toTimestamp(ioBasic(t)); | |
| 2771 | try batchDrainSubmittedWindows(b, true); | |
| 2659 | const deadline: ?Io.Clock.Timestamp = timeout.toTimestamp(io(t)); | |
| 2660 | try batchDrainSubmittedWindows(t, b, true); | |
| 2772 | 2661 | while (b.pending.head != .none and b.completed.head == .none) { |
| 2773 | 2662 | var delay_interval: windows.LARGE_INTEGER = interval: { |
| 2774 | 2663 | const d = deadline orelse break :interval std.math.minInt(windows.LARGE_INTEGER); |
| ... | ... | @@ -2796,12 +2685,12 @@ fn batchAwaitConcurrent(userdata: ?*anyopaque, b: *Io.Batch, timeout: Io.Timeout |
| 2796 | 2685 | if (!have_poll) return error.ConcurrencyUnavailable; |
| 2797 | 2686 | var poll_buffer: [poll_buffer_len]posix.pollfd = undefined; |
| 2798 | 2687 | var poll_storage: struct { |
| 2799 | gpa: std.mem.Allocator, | |
| 2688 | gpa: Allocator, | |
| 2800 | 2689 | batch: *Io.Batch, |
| 2801 | 2690 | slice: []posix.pollfd, |
| 2802 | 2691 | len: u32, |
| 2803 | 2692 | |
| 2804 | fn add(storage: *@This(), file: Io.File, events: @FieldType(posix.pollfd, "events")) Io.ConcurrentError!void { | |
| 2693 | fn add(storage: *@This(), fd: File.Handle, events: @FieldType(posix.pollfd, "events")) Io.ConcurrentError!void { | |
| 2805 | 2694 | const len = storage.len; |
| 2806 | 2695 | if (len == poll_buffer_len) { |
| 2807 | 2696 | const slice: []posix.pollfd = if (storage.batch.userdata) |batch_userdata| |
| ... | ... | @@ -2816,7 +2705,7 @@ fn batchAwaitConcurrent(userdata: ?*anyopaque, b: *Io.Batch, timeout: Io.Timeout |
| 2816 | 2705 | storage.slice = slice; |
| 2817 | 2706 | } |
| 2818 | 2707 | storage.slice[len] = .{ |
| 2819 | .fd = file.handle, | |
| 2708 | .fd = fd, | |
| 2820 | 2709 | .events = events, |
| 2821 | 2710 | .revents = 0, |
| 2822 | 2711 | }; |
| ... | ... | @@ -2826,18 +2715,41 @@ fn batchAwaitConcurrent(userdata: ?*anyopaque, b: *Io.Batch, timeout: Io.Timeout |
| 2826 | 2715 | { |
| 2827 | 2716 | var index = b.submitted.head; |
| 2828 | 2717 | while (index != .none) { |
| 2829 | const submission = &b.storage[index.toIndex()].submission; | |
| 2718 | const storage = &b.storage[index.toIndex()]; | |
| 2719 | const submission = storage.submission; | |
| 2830 | 2720 | switch (submission.operation) { |
| 2831 | .file_read_streaming => |o| try poll_storage.add(o.file, posix.POLL.IN), | |
| 2832 | .file_write_streaming => |o| try poll_storage.add(o.file, posix.POLL.OUT), | |
| 2833 | .device_io_control => |o| try poll_storage.add(o.file, posix.POLL.IN | posix.POLL.OUT | posix.POLL.ERR), | |
| 2721 | .file_read_streaming => |o| try poll_storage.add(o.file.handle, posix.POLL.IN | posix.POLL.ERR), | |
| 2722 | .file_write_streaming => |o| try poll_storage.add(o.file.handle, posix.POLL.OUT | posix.POLL.ERR), | |
| 2723 | .device_io_control => |o| try poll_storage.add(o.file.handle, posix.POLL.IN | posix.POLL.OUT | posix.POLL.ERR), | |
| 2724 | .net_receive => |*o| nb: { | |
| 2725 | var data_i: usize = 0; | |
| 2726 | const result: Io.Operation.Result = .{ .net_receive = for (o.message_buffer, 0..) |*msg, msg_i| { | |
| 2727 | const remaining_data_buffer = o.data_buffer[data_i..]; | |
| 2728 | netReceivePosix(o.socket_handle, msg, remaining_data_buffer, o.flags, true) catch |err| switch (err) { | |
| 2729 | error.Canceled => |e| return e, | |
| 2730 | error.WouldBlock => { | |
| 2731 | if (msg_i != 0) break .{ null, msg_i }; | |
| 2732 | try poll_storage.add(o.socket_handle, posix.POLL.IN | posix.POLL.ERR); | |
| 2733 | break :nb; | |
| 2734 | }, | |
| 2735 | else => |e| break .{ e, 0 }, | |
| 2736 | }; | |
| 2737 | data_i += msg.data.len; | |
| 2738 | } else .{ null, o.message_buffer.len } }; | |
| 2739 | switch (b.completed.tail) { | |
| 2740 | .none => b.completed.head = index, | |
| 2741 | else => |tail_index| b.storage[tail_index.toIndex()].completion.node.next = index, | |
| 2742 | } | |
| 2743 | storage.* = .{ .completion = .{ .node = .{ .next = .none }, .result = result } }; | |
| 2744 | b.completed.tail = index; | |
| 2745 | }, | |
| 2834 | 2746 | } |
| 2835 | 2747 | index = submission.node.next; |
| 2836 | 2748 | } |
| 2837 | 2749 | } |
| 2838 | 2750 | switch (poll_storage.len) { |
| 2839 | 2751 | 0 => return, |
| 2840 | 1 => if (timeout == .none) { | |
| 2752 | 1 => if (timeout == .none and b.completed.head == .none) { | |
| 2841 | 2753 | const index = b.submitted.head; |
| 2842 | 2754 | const storage = &b.storage[index.toIndex()]; |
| 2843 | 2755 | const result = try operate(t, storage.submission.operation); |
| ... | ... | @@ -2854,7 +2766,7 @@ fn batchAwaitConcurrent(userdata: ?*anyopaque, b: *Io.Batch, timeout: Io.Timeout |
| 2854 | 2766 | }, |
| 2855 | 2767 | else => {}, |
| 2856 | 2768 | } |
| 2857 | const t_io = ioBasic(t); | |
| 2769 | const t_io = io(t); | |
| 2858 | 2770 | const deadline = timeout.toTimestamp(t_io); |
| 2859 | 2771 | while (true) { |
| 2860 | 2772 | const timeout_ms: i32 = t: { |
| ... | ... | @@ -2961,6 +2873,31 @@ fn batchCancel(userdata: ?*anyopaque, b: *Io.Batch) void { |
| 2961 | 2873 | } |
| 2962 | 2874 | } |
| 2963 | 2875 | |
| 2876 | fn batchCompleteBlockingWindows( | |
| 2877 | b: *Io.Batch, | |
| 2878 | operation_userdata: *WindowsBatchOperationUserdata, | |
| 2879 | result: Io.Operation.Result, | |
| 2880 | ) void { | |
| 2881 | const erased_userdata = operation_userdata.toErased(); | |
| 2882 | const pending: *Io.Operation.Storage.Pending = @fieldParentPtr("userdata", erased_userdata); | |
| 2883 | switch (pending.node.prev) { | |
| 2884 | .none => b.pending.head = pending.node.next, | |
| 2885 | else => |prev_index| b.storage[prev_index.toIndex()].pending.node.next = pending.node.next, | |
| 2886 | } | |
| 2887 | switch (pending.node.next) { | |
| 2888 | .none => b.pending.tail = pending.node.prev, | |
| 2889 | else => |next_index| b.storage[next_index.toIndex()].pending.node.prev = pending.node.prev, | |
| 2890 | } | |
| 2891 | const storage: *Io.Operation.Storage = @fieldParentPtr("pending", pending); | |
| 2892 | const index: Io.Operation.OptionalIndex = .fromIndex(storage - b.storage.ptr); | |
| 2893 | switch (b.completed.tail) { | |
| 2894 | .none => b.completed.head = index, | |
| 2895 | else => |tail_index| b.storage[tail_index.toIndex()].completion.node.next = index, | |
| 2896 | } | |
| 2897 | b.completed.tail = index; | |
| 2898 | storage.* = .{ .completion = .{ .node = .{ .next = .none }, .result = result } }; | |
| 2899 | } | |
| 2900 | ||
| 2964 | 2901 | fn batchApc( |
| 2965 | 2902 | apc_context: ?*anyopaque, |
| 2966 | 2903 | iosb: *windows.IO_STATUS_BLOCK, |
| ... | ... | @@ -3000,6 +2937,7 @@ fn batchApc( |
| 3000 | 2937 | .file_read_streaming => .{ .file_read_streaming = ntReadFileResult(iosb) }, |
| 3001 | 2938 | .file_write_streaming => .{ .file_write_streaming = ntWriteFileResult(iosb) }, |
| 3002 | 2939 | .device_io_control => .{ .device_io_control = iosb.* }, |
| 2940 | .net_receive => unreachable, | |
| 3003 | 2941 | }; |
| 3004 | 2942 | storage.* = .{ .completion = .{ .node = .{ .next = .none }, .result = result } }; |
| 3005 | 2943 | }, |
| ... | ... | @@ -3007,7 +2945,7 @@ fn batchApc( |
| 3007 | 2945 | } |
| 3008 | 2946 | |
| 3009 | 2947 | /// If `concurrency` is false, `error.ConcurrencyUnavailable` is unreachable. |
| 3010 | fn batchDrainSubmittedWindows(b: *Io.Batch, concurrency: bool) (Io.ConcurrentError || Io.Cancelable)!void { | |
| 2948 | fn batchDrainSubmittedWindows(t: *Threaded, b: *Io.Batch, concurrency: bool) (Io.ConcurrentError || Io.Cancelable)!void { | |
| 3011 | 2949 | var index = b.submitted.head; |
| 3012 | 2950 | errdefer b.submitted.head = index; |
| 3013 | 2951 | while (index != .none) { |
| ... | ... | @@ -3201,6 +3139,13 @@ fn batchDrainSubmittedWindows(b: *Io.Batch, concurrency: bool) (Io.ConcurrentErr |
| 3201 | 3139 | }; |
| 3202 | 3140 | } |
| 3203 | 3141 | }, |
| 3142 | .net_receive => |*o| { | |
| 3143 | // TODO integrate with overlapped I/O or equivalent to avoid this error | |
| 3144 | if (concurrency) return error.ConcurrencyUnavailable; | |
| 3145 | batchCompleteBlockingWindows(b, operation_userdata, .{ | |
| 3146 | .net_receive = netReceiveWindows(t, o.socket_handle, o.message_buffer, o.data_buffer, o.flags), | |
| 3147 | }); | |
| 3148 | }, | |
| 3204 | 3149 | } |
| 3205 | 3150 | index = submission.node.next; |
| 3206 | 3151 | } |
| ... | ... | @@ -3459,7 +3404,7 @@ fn dirCreateDirPathOpenPosix( |
| 3459 | 3404 | options: Dir.OpenOptions, |
| 3460 | 3405 | ) Dir.CreateDirPathOpenError!Dir { |
| 3461 | 3406 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| 3462 | const t_io = ioBasic(t); | |
| 3407 | const t_io = io(t); | |
| 3463 | 3408 | return dirOpenDirPosix(t, dir, sub_path, options) catch |err| switch (err) { |
| 3464 | 3409 | error.FileNotFound => { |
| 3465 | 3410 | _ = try dir.createDirPathStatus(t_io, sub_path, permissions); |
| ... | ... | @@ -3580,7 +3525,7 @@ fn dirCreateDirPathOpenWasi( |
| 3580 | 3525 | options: Dir.OpenOptions, |
| 3581 | 3526 | ) Dir.CreateDirPathOpenError!Dir { |
| 3582 | 3527 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| 3583 | const t_io = ioBasic(t); | |
| 3528 | const t_io = io(t); | |
| 3584 | 3529 | return dirOpenDirWasi(t, dir, sub_path, options) catch |err| switch (err) { |
| 3585 | 3530 | error.FileNotFound => { |
| 3586 | 3531 | _ = try dir.createDirPathStatus(t_io, sub_path, permissions); |
| ... | ... | @@ -4621,7 +4566,7 @@ fn dirCreateFileAtomic( |
| 4621 | 4566 | options: Dir.CreateFileAtomicOptions, |
| 4622 | 4567 | ) Dir.CreateFileAtomicError!File.Atomic { |
| 4623 | 4568 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| 4624 | const t_io = ioBasic(t); | |
| 4569 | const t_io = io(t); | |
| 4625 | 4570 | |
| 4626 | 4571 | // Linux has O_TMPFILE, but linkat() does not support AT_REPLACE, so it's |
| 4627 | 4572 | // useless when we have to make up a bogus path name to do the rename() |
| ... | ... | @@ -10249,19 +10194,19 @@ fn processExecutablePath(userdata: ?*anyopaque, out_buffer: []u8) process.Execut |
| 10249 | 10194 | const rc = std.c._NSGetExecutablePath(&symlink_path_buf, &n); |
| 10250 | 10195 | if (rc != 0) return error.NameTooLong; |
| 10251 | 10196 | const symlink_path = std.mem.sliceTo(&symlink_path_buf, 0); |
| 10252 | return Io.Dir.realPathFileAbsolute(ioBasic(t), symlink_path, out_buffer) catch |err| switch (err) { | |
| 10197 | return Io.Dir.realPathFileAbsolute(io(t), symlink_path, out_buffer) catch |err| switch (err) { | |
| 10253 | 10198 | error.NetworkNotFound => unreachable, // Windows-only |
| 10254 | 10199 | error.FileBusy => unreachable, // Windows-only |
| 10255 | 10200 | else => |e| return e, |
| 10256 | 10201 | }; |
| 10257 | 10202 | }, |
| 10258 | .linux, .serenity => return Io.Dir.readLinkAbsolute(ioBasic(t), "/proc/self/exe", out_buffer) catch |err| switch (err) { | |
| 10203 | .linux, .serenity => return Io.Dir.readLinkAbsolute(io(t), "/proc/self/exe", out_buffer) catch |err| switch (err) { | |
| 10259 | 10204 | error.UnsupportedReparsePointType => unreachable, // Windows-only |
| 10260 | 10205 | error.NetworkNotFound => unreachable, // Windows-only |
| 10261 | 10206 | error.FileBusy => unreachable, // Windows-only |
| 10262 | 10207 | else => |e| return e, |
| 10263 | 10208 | }, |
| 10264 | .illumos => return Io.Dir.readLinkAbsolute(ioBasic(t), "/proc/self/path/a.out", out_buffer) catch |err| switch (err) { | |
| 10209 | .illumos => return Io.Dir.readLinkAbsolute(io(t), "/proc/self/path/a.out", out_buffer) catch |err| switch (err) { | |
| 10265 | 10210 | error.UnsupportedReparsePointType => unreachable, // Windows-only |
| 10266 | 10211 | error.NetworkNotFound => unreachable, // Windows-only |
| 10267 | 10212 | error.FileBusy => unreachable, // Windows-only |
| ... | ... | @@ -11623,7 +11568,7 @@ fn sleepPosix(timeout: Io.Timeout) Io.Cancelable!void { |
| 11623 | 11568 | } |
| 11624 | 11569 | |
| 11625 | 11570 | fn sleepWasi(t: *Threaded, timeout: Io.Timeout) Io.Cancelable!void { |
| 11626 | const t_io = ioBasic(t); | |
| 11571 | const t_io = io(t); | |
| 11627 | 11572 | const w = std.os.wasi; |
| 11628 | 11573 | |
| 11629 | 11574 | const clock: w.subscription_clock_t = if (timeout.toDurationFromNow(t_io)) |d| .{ |
| ... | ... | @@ -11652,7 +11597,7 @@ fn sleepWasi(t: *Threaded, timeout: Io.Timeout) Io.Cancelable!void { |
| 11652 | 11597 | } |
| 11653 | 11598 | |
| 11654 | 11599 | fn sleepNanosleep(t: *Threaded, timeout: Io.Timeout) Io.Cancelable!void { |
| 11655 | const t_io = ioBasic(t); | |
| 11600 | const t_io = io(t); | |
| 11656 | 11601 | const sec_type = @typeInfo(posix.timespec).@"struct".fields[0].type; |
| 11657 | 11602 | const nsec_type = @typeInfo(posix.timespec).@"struct".fields[1].type; |
| 11658 | 11603 | |
| ... | ... | @@ -11884,6 +11829,7 @@ fn netListenUnixWindows( |
| 11884 | 11829 | options: net.UnixAddress.ListenOptions, |
| 11885 | 11830 | ) net.UnixAddress.ListenError!net.Socket.Handle { |
| 11886 | 11831 | if (!net.has_unix_sockets) return error.AddressFamilyUnsupported; |
| 11832 | if (!have_networking) return error.NetworkDown; | |
| 11887 | 11833 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| 11888 | 11834 | |
| 11889 | 11835 | const socket_handle = openSocketWsa(t, posix.AF.UNIX, .{ .mode = .stream }) catch |err| switch (err) { |
| ... | ... | @@ -12380,6 +12326,7 @@ fn netConnectUnixWindows( |
| 12380 | 12326 | address: *const net.UnixAddress, |
| 12381 | 12327 | ) net.UnixAddress.ConnectError!net.Socket.Handle { |
| 12382 | 12328 | if (!net.has_unix_sockets) return error.AddressFamilyUnsupported; |
| 12329 | if (!have_networking) return error.NetworkDown; | |
| 12383 | 12330 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| 12384 | 12331 | |
| 12385 | 12332 | const socket_handle = try openSocketWsa(t, posix.AF.UNIX, .{ .mode = .stream }); |
| ... | ... | @@ -12995,11 +12942,76 @@ fn netSendWindows( |
| 12995 | 12942 | ) struct { ?net.Socket.SendError, usize } { |
| 12996 | 12943 | if (!have_networking) return .{ error.NetworkDown, 0 }; |
| 12997 | 12944 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| 12998 | _ = t; | |
| 12999 | _ = handle; | |
| 13000 | _ = messages; | |
| 13001 | _ = flags; | |
| 13002 | @panic("TODO netSendWindows"); | |
| 12945 | ||
| 12946 | // Ignored flags: confirm, eor, fastopen | |
| 12947 | const windows_flags: u32 = | |
| 12948 | @as(u32, if (flags.oob) ws2_32.MSG.OOB else 0) | | |
| 12949 | @as(u32, if (flags.dont_route) ws2_32.MSG.DONTROUTE else 0); | |
| 12950 | ||
| 12951 | for (messages, 0..) |*m, i| { | |
| 12952 | netSendWindowsOne(t, handle, m, windows_flags) catch |err| return .{ err, i }; | |
| 12953 | } | |
| 12954 | return .{ null, messages.len }; | |
| 12955 | } | |
| 12956 | ||
| 12957 | fn netSendWindowsOne( | |
| 12958 | t: *Threaded, | |
| 12959 | handle: net.Socket.Handle, | |
| 12960 | message: *net.OutgoingMessage, | |
| 12961 | flags: u32, | |
| 12962 | ) net.Socket.SendError!void { | |
| 12963 | var buf: ws2_32.WSABUF = .{ | |
| 12964 | .buf = @constCast(message.data_ptr), | |
| 12965 | .len = std.math.cast(u32, message.data_len) orelse return error.MessageOversize, | |
| 12966 | }; | |
| 12967 | var n: u32 = undefined; | |
| 12968 | var address: WsaAddress = undefined; | |
| 12969 | const address_size = addressToWsa(message.address, &address); | |
| 12970 | var syscall: Syscall = try .start(); | |
| 12971 | while (true) { | |
| 12972 | const rc = ws2_32.WSASendTo( | |
| 12973 | handle, | |
| 12974 | (&buf)[0..1], | |
| 12975 | 1, | |
| 12976 | &n, | |
| 12977 | flags, | |
| 12978 | &address.any, | |
| 12979 | address_size, | |
| 12980 | null, | |
| 12981 | null, | |
| 12982 | ); | |
| 12983 | if (rc != ws2_32.SOCKET_ERROR) { | |
| 12984 | syscall.finish(); | |
| 12985 | return; | |
| 12986 | } | |
| 12987 | switch (ws2_32.WSAGetLastError()) { | |
| 12988 | .EINTR, .ECANCELLED, .E_CANCELLED, .OPERATION_ABORTED => { | |
| 12989 | try syscall.checkCancel(); | |
| 12990 | continue; | |
| 12991 | }, | |
| 12992 | .NOTINITIALISED => { | |
| 12993 | syscall.finish(); | |
| 12994 | try initializeWsa(t); | |
| 12995 | syscall = try .start(); | |
| 12996 | continue; | |
| 12997 | }, | |
| 12998 | ||
| 12999 | .ECONNRESET => return syscall.fail(error.ConnectionResetByPeer), | |
| 13000 | .ENETDOWN => return syscall.fail(error.NetworkDown), | |
| 13001 | .ENETRESET => return syscall.fail(error.ConnectionResetByPeer), | |
| 13002 | .ENOTCONN => return syscall.fail(error.SocketUnconnected), | |
| 13003 | .EFAULT => unreachable, // a pointer is not completely contained in user address space. | |
| 13004 | ||
| 13005 | else => |err| { | |
| 13006 | syscall.finish(); | |
| 13007 | switch (err) { | |
| 13008 | .EINVAL => return wsaErrorBug(err), | |
| 13009 | .EMSGSIZE => return wsaErrorBug(err), | |
| 13010 | else => return windows.unexpectedWSAError(err), | |
| 13011 | } | |
| 13012 | }, | |
| 13013 | } | |
| 13014 | } | |
| 13003 | 13015 | } |
| 13004 | 13016 | |
| 13005 | 13017 | fn netSendUnavailable( |
| ... | ... | @@ -13190,70 +13202,44 @@ fn netSendMany( |
| 13190 | 13202 | } |
| 13191 | 13203 | |
| 13192 | 13204 | fn netReceivePosix( |
| 13193 | userdata: ?*anyopaque, | |
| 13194 | handle: net.Socket.Handle, | |
| 13195 | message_buffer: []net.IncomingMessage, | |
| 13205 | socket_handle: net.Socket.Handle, | |
| 13206 | message: *net.IncomingMessage, | |
| 13196 | 13207 | data_buffer: []u8, |
| 13197 | 13208 | flags: net.ReceiveFlags, |
| 13198 | timeout: Io.Timeout, | |
| 13199 | ) struct { ?net.Socket.ReceiveTimeoutError, usize } { | |
| 13200 | if (!have_networking) return .{ error.NetworkDown, 0 }; | |
| 13201 | const t: *Threaded = @ptrCast(@alignCast(userdata)); | |
| 13202 | const t_io = io(t); | |
| 13203 | ||
| 13209 | nonblocking: bool, | |
| 13210 | ) (net.Socket.ReceiveError || error{WouldBlock})!void { | |
| 13204 | 13211 | // recvmmsg is useless, here's why: |
| 13205 | 13212 | // * [timeout bug](https://bugzilla.kernel.org/show_bug.cgi?id=75371) |
| 13206 | 13213 | // * it wants iovecs for each message but we have a better API: one data |
| 13207 | 13214 | // buffer to handle all the messages. The better API cannot be lowered to |
| 13208 | 13215 | // the split vectors though because reducing the buffer size might make |
| 13209 | 13216 | // some messages unreceivable. |
| 13210 | ||
| 13211 | // So the strategy instead is to use non-blocking recvmsg calls, calling | |
| 13212 | // poll() with timeout if the first one returns EAGAIN. | |
| 13213 | 13217 | const posix_flags: u32 = |
| 13214 | 13218 | @as(u32, if (flags.oob) posix.MSG.OOB else 0) | |
| 13215 | 13219 | @as(u32, if (flags.peek) posix.MSG.PEEK else 0) | |
| 13216 | 13220 | @as(u32, if (flags.trunc) posix.MSG.TRUNC else 0) | |
| 13217 | posix.MSG.DONTWAIT | posix.MSG.NOSIGNAL; | |
| 13221 | posix.MSG.NOSIGNAL | | |
| 13222 | @as(u32, if (nonblocking) posix.MSG.DONTWAIT else 0); | |
| 13218 | 13223 | |
| 13219 | var poll_fds: [1]posix.pollfd = .{ | |
| 13220 | .{ | |
| 13221 | .fd = handle, | |
| 13222 | .events = posix.POLL.IN, | |
| 13223 | .revents = undefined, | |
| 13224 | }, | |
| 13224 | var storage: PosixAddress = undefined; | |
| 13225 | var iov: posix.iovec = .{ .base = data_buffer.ptr, .len = data_buffer.len }; | |
| 13226 | var msg: posix.msghdr = .{ | |
| 13227 | .name = &storage.any, | |
| 13228 | .namelen = @sizeOf(PosixAddress), | |
| 13229 | .iov = (&iov)[0..1], | |
| 13230 | .iovlen = 1, | |
| 13231 | .control = message.control.ptr, | |
| 13232 | .controllen = @intCast(message.control.len), | |
| 13233 | .flags = undefined, | |
| 13225 | 13234 | }; |
| 13226 | var message_i: usize = 0; | |
| 13227 | var data_i: usize = 0; | |
| 13228 | 13235 | |
| 13229 | const deadline = timeout.toTimestamp(t_io); | |
| 13230 | ||
| 13231 | recv: while (true) { | |
| 13232 | if (message_buffer.len - message_i == 0) return .{ null, message_i }; | |
| 13233 | const message = &message_buffer[message_i]; | |
| 13234 | const remaining_data_buffer = data_buffer[data_i..]; | |
| 13235 | var storage: PosixAddress = undefined; | |
| 13236 | var iov: posix.iovec = .{ .base = remaining_data_buffer.ptr, .len = remaining_data_buffer.len }; | |
| 13237 | var msg: posix.msghdr = .{ | |
| 13238 | .name = &storage.any, | |
| 13239 | .namelen = @sizeOf(PosixAddress), | |
| 13240 | .iov = (&iov)[0..1], | |
| 13241 | .iovlen = 1, | |
| 13242 | .control = message.control.ptr, | |
| 13243 | .controllen = @intCast(message.control.len), | |
| 13244 | .flags = undefined, | |
| 13245 | }; | |
| 13246 | ||
| 13247 | const recv_rc = rc: { | |
| 13248 | const syscall = Syscall.start() catch |err| return .{ err, message_i }; | |
| 13249 | const rc = posix.system.recvmsg(handle, &msg, posix_flags); | |
| 13250 | syscall.finish(); | |
| 13251 | break :rc rc; | |
| 13252 | }; | |
| 13253 | switch (posix.errno(recv_rc)) { | |
| 13236 | const syscall = try Syscall.start(); | |
| 13237 | while (true) { | |
| 13238 | const rc = posix.system.recvmsg(socket_handle, &msg, posix_flags); | |
| 13239 | switch (posix.errno(rc)) { | |
| 13254 | 13240 | .SUCCESS => { |
| 13255 | const data = remaining_data_buffer[0..@intCast(recv_rc)]; | |
| 13256 | data_i += data.len; | |
| 13241 | syscall.finish(); | |
| 13242 | const data = data_buffer[0..@intCast(rc)]; | |
| 13257 | 13243 | message.* = .{ |
| 13258 | 13244 | .from = addressFromPosix(&storage), |
| 13259 | 13245 | .data = data, |
| ... | ... | @@ -13266,96 +13252,122 @@ fn netReceivePosix( |
| 13266 | 13252 | .errqueue = if (@hasDecl(posix.MSG, "ERRQUEUE")) (msg.flags & posix.MSG.ERRQUEUE) != 0 else false, |
| 13267 | 13253 | }, |
| 13268 | 13254 | }; |
| 13269 | message_i += 1; | |
| 13270 | continue; | |
| 13255 | return; | |
| 13271 | 13256 | }, |
| 13272 | .AGAIN => while (true) { | |
| 13273 | if (message_i != 0) return .{ null, message_i }; | |
| 13274 | ||
| 13275 | const max_poll_ms = std.math.maxInt(u31); | |
| 13276 | const timeout_ms: u31 = if (deadline) |d| t: { | |
| 13277 | const duration = d.durationFromNow(t_io); | |
| 13278 | if (duration.raw.nanoseconds <= 0) return .{ error.Timeout, message_i }; | |
| 13279 | break :t @intCast(@min(max_poll_ms, duration.raw.toMilliseconds())); | |
| 13280 | } else max_poll_ms; | |
| 13281 | ||
| 13282 | const syscall = Syscall.start() catch |err| return .{ err, message_i }; | |
| 13283 | const poll_rc = posix.system.poll(&poll_fds, poll_fds.len, timeout_ms); | |
| 13284 | syscall.finish(); | |
| 13285 | ||
| 13286 | switch (posix.errno(poll_rc)) { | |
| 13287 | .SUCCESS => { | |
| 13288 | if (poll_rc == 0) { | |
| 13289 | // Although spurious timeouts are OK, when no deadline | |
| 13290 | // is passed we must not return `error.Timeout`. | |
| 13291 | if (deadline == null) continue; | |
| 13292 | return .{ error.Timeout, message_i }; | |
| 13293 | } | |
| 13294 | continue :recv; | |
| 13295 | }, | |
| 13296 | .INTR => continue, | |
| 13297 | ||
| 13298 | .FAULT => |err| return .{ errnoBug(err), message_i }, | |
| 13299 | .INVAL => |err| return .{ errnoBug(err), message_i }, | |
| 13300 | .NOMEM => return .{ error.SystemResources, message_i }, | |
| 13301 | else => |err| return .{ posix.unexpectedErrno(err), message_i }, | |
| 13302 | } | |
| 13257 | .INTR => { | |
| 13258 | try syscall.checkCancel(); | |
| 13259 | continue; | |
| 13303 | 13260 | }, |
| 13304 | .INTR => continue, | |
| 13305 | ||
| 13306 | .BADF => |err| return .{ errnoBug(err), message_i }, | |
| 13307 | .NFILE => return .{ error.SystemFdQuotaExceeded, message_i }, | |
| 13308 | .MFILE => return .{ error.ProcessFdQuotaExceeded, message_i }, | |
| 13309 | .FAULT => |err| return .{ errnoBug(err), message_i }, | |
| 13310 | .INVAL => |err| return .{ errnoBug(err), message_i }, | |
| 13311 | .NOBUFS => return .{ error.SystemResources, message_i }, | |
| 13312 | .NOMEM => return .{ error.SystemResources, message_i }, | |
| 13313 | .NOTCONN => return .{ error.SocketUnconnected, message_i }, | |
| 13314 | .NOTSOCK => |err| return .{ errnoBug(err), message_i }, | |
| 13315 | .MSGSIZE => return .{ error.MessageOversize, message_i }, | |
| 13316 | .PIPE => return .{ error.SocketUnconnected, message_i }, | |
| 13317 | .OPNOTSUPP => |err| return .{ errnoBug(err), message_i }, | |
| 13318 | .CONNRESET => return .{ error.ConnectionResetByPeer, message_i }, | |
| 13319 | .NETDOWN => return .{ error.NetworkDown, message_i }, | |
| 13320 | else => |err| return .{ posix.unexpectedErrno(err), message_i }, | |
| 13261 | .NFILE => return syscall.fail(error.SystemFdQuotaExceeded), | |
| 13262 | .MFILE => return syscall.fail(error.ProcessFdQuotaExceeded), | |
| 13263 | .NOBUFS => return syscall.fail(error.SystemResources), | |
| 13264 | .NOMEM => return syscall.fail(error.SystemResources), | |
| 13265 | .NOTCONN => return syscall.fail(error.SocketUnconnected), | |
| 13266 | .MSGSIZE => return syscall.fail(error.MessageOversize), | |
| 13267 | .PIPE => return syscall.fail(error.SocketUnconnected), | |
| 13268 | .CONNRESET => return syscall.fail(error.ConnectionResetByPeer), | |
| 13269 | .NETDOWN => return syscall.fail(error.NetworkDown), | |
| 13270 | .AGAIN => return syscall.fail(error.WouldBlock), | |
| 13271 | .BADF => |err| return syscall.errnoBug(err), | |
| 13272 | .FAULT => |err| return syscall.errnoBug(err), | |
| 13273 | .INVAL => |err| return syscall.errnoBug(err), | |
| 13274 | .NOTSOCK => |err| return syscall.errnoBug(err), | |
| 13275 | .OPNOTSUPP => |err| return syscall.errnoBug(err), | |
| 13276 | else => |err| return syscall.unexpectedErrno(err), | |
| 13321 | 13277 | } |
| 13322 | 13278 | } |
| 13323 | 13279 | } |
| 13324 | 13280 | |
| 13325 | 13281 | fn netReceiveWindows( |
| 13326 | userdata: ?*anyopaque, | |
| 13327 | handle: net.Socket.Handle, | |
| 13282 | t: *Threaded, | |
| 13283 | socket_handle: net.Socket.Handle, | |
| 13328 | 13284 | message_buffer: []net.IncomingMessage, |
| 13329 | 13285 | data_buffer: []u8, |
| 13330 | 13286 | flags: net.ReceiveFlags, |
| 13331 | timeout: Io.Timeout, | |
| 13332 | ) struct { ?net.Socket.ReceiveTimeoutError, usize } { | |
| 13333 | if (!have_networking) return .{ error.NetworkDown, 0 }; | |
| 13334 | const t: *Threaded = @ptrCast(@alignCast(userdata)); | |
| 13335 | _ = t; | |
| 13336 | _ = handle; | |
| 13337 | _ = message_buffer; | |
| 13338 | _ = data_buffer; | |
| 13339 | _ = flags; | |
| 13340 | _ = timeout; | |
| 13341 | @panic("TODO implement netReceiveWindows"); | |
| 13287 | ) struct { ?net.Socket.ReceiveError, usize } { | |
| 13288 | netReceiveWindowsOne(t, socket_handle, &message_buffer[0], data_buffer, flags) catch |err| return .{ err, 0 }; | |
| 13289 | return .{ null, 1 }; | |
| 13342 | 13290 | } |
| 13343 | 13291 | |
| 13344 | fn netReceiveUnavailable( | |
| 13345 | userdata: ?*anyopaque, | |
| 13346 | handle: net.Socket.Handle, | |
| 13347 | message_buffer: []net.IncomingMessage, | |
| 13292 | fn netReceiveWindowsOne( | |
| 13293 | t: *Threaded, | |
| 13294 | socket_handle: net.Socket.Handle, | |
| 13295 | message: *net.IncomingMessage, | |
| 13348 | 13296 | data_buffer: []u8, |
| 13349 | 13297 | flags: net.ReceiveFlags, |
| 13350 | timeout: Io.Timeout, | |
| 13351 | ) struct { ?net.Socket.ReceiveTimeoutError, usize } { | |
| 13352 | _ = userdata; | |
| 13353 | _ = handle; | |
| 13354 | _ = message_buffer; | |
| 13355 | _ = data_buffer; | |
| 13356 | _ = flags; | |
| 13357 | _ = timeout; | |
| 13358 | return .{ error.NetworkDown, 0 }; | |
| 13298 | ) net.Socket.ReceiveError!void { | |
| 13299 | if (!have_networking) return error.NetworkDown; | |
| 13300 | ||
| 13301 | var windows_flags: u32 = | |
| 13302 | @as(u32, if (flags.oob) ws2_32.MSG.OOB else 0) | | |
| 13303 | @as(u32, if (flags.peek) ws2_32.MSG.PEEK else 0) | | |
| 13304 | @as(u32, if (flags.trunc) ws2_32.MSG.TRUNC else 0); | |
| 13305 | ||
| 13306 | var buf: ws2_32.WSABUF = .{ | |
| 13307 | .buf = data_buffer.ptr, | |
| 13308 | .len = std.math.cast(u32, data_buffer.len) orelse return error.MessageOversize, | |
| 13309 | }; | |
| 13310 | var n: u32 = undefined; | |
| 13311 | var syscall: Syscall = try .start(); | |
| 13312 | var from_storage: WsaAddress = undefined; | |
| 13313 | var from_storage_len: i32 = @sizeOf(WsaAddress); | |
| 13314 | ||
| 13315 | while (true) { | |
| 13316 | const rc = ws2_32.WSARecvFrom( | |
| 13317 | socket_handle, | |
| 13318 | (&buf)[0..1], | |
| 13319 | 1, | |
| 13320 | &n, | |
| 13321 | &windows_flags, | |
| 13322 | &from_storage.any, | |
| 13323 | &from_storage_len, | |
| 13324 | null, | |
| 13325 | null, | |
| 13326 | ); | |
| 13327 | if (rc != ws2_32.SOCKET_ERROR) { | |
| 13328 | syscall.finish(); | |
| 13329 | message.* = .{ | |
| 13330 | .from = addressFromWsa(&from_storage), | |
| 13331 | .data = data_buffer[0..n], | |
| 13332 | .control = &.{}, | |
| 13333 | .flags = .{ | |
| 13334 | .eor = false, | |
| 13335 | .trunc = (windows_flags & ws2_32.MSG.TRUNC) != 0, | |
| 13336 | .ctrunc = (windows_flags & ws2_32.MSG.CTRUNC) != 0, | |
| 13337 | .oob = false, | |
| 13338 | .errqueue = false, | |
| 13339 | }, | |
| 13340 | }; | |
| 13341 | return; | |
| 13342 | } | |
| 13343 | switch (ws2_32.WSAGetLastError()) { | |
| 13344 | .EINTR, .ECANCELLED, .E_CANCELLED, .OPERATION_ABORTED => { | |
| 13345 | try syscall.checkCancel(); | |
| 13346 | continue; | |
| 13347 | }, | |
| 13348 | .NOTINITIALISED => { | |
| 13349 | syscall.finish(); | |
| 13350 | try initializeWsa(t); | |
| 13351 | syscall = try .start(); | |
| 13352 | continue; | |
| 13353 | }, | |
| 13354 | ||
| 13355 | .ECONNRESET => return syscall.fail(error.ConnectionResetByPeer), | |
| 13356 | .ENETDOWN => return syscall.fail(error.NetworkDown), | |
| 13357 | .ENETRESET => return syscall.fail(error.ConnectionResetByPeer), | |
| 13358 | .ENOTCONN => return syscall.fail(error.SocketUnconnected), | |
| 13359 | .EFAULT => unreachable, // a pointer is not completely contained in user address space. | |
| 13360 | ||
| 13361 | else => |err| { | |
| 13362 | syscall.finish(); | |
| 13363 | switch (err) { | |
| 13364 | .EINVAL => return wsaErrorBug(err), | |
| 13365 | .EMSGSIZE => return wsaErrorBug(err), | |
| 13366 | else => return windows.unexpectedWSAError(err), | |
| 13367 | } | |
| 13368 | }, | |
| 13369 | } | |
| 13370 | } | |
| 13359 | 13371 | } |
| 13360 | 13372 | |
| 13361 | 13373 | fn netWritePosix( |
| ... | ... | @@ -13459,6 +13471,7 @@ fn netWriteWindows( |
| 13459 | 13471 | data: []const []const u8, |
| 13460 | 13472 | splat: usize, |
| 13461 | 13473 | ) net.Stream.Writer.Error!usize { |
| 13474 | if (!have_networking) return error.NetworkDown; | |
| 13462 | 13475 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| 13463 | 13476 | comptime assert(is_windows); |
| 13464 | 13477 | |
| ... | ... | @@ -13581,6 +13594,7 @@ fn addBuf(v: []posix.iovec_const, i: *iovlen_t, bytes: []const u8) void { |
| 13581 | 13594 | } |
| 13582 | 13595 | |
| 13583 | 13596 | fn netClose(userdata: ?*anyopaque, handles: []const net.Socket.Handle) void { |
| 13597 | if (!have_networking) unreachable; | |
| 13584 | 13598 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| 13585 | 13599 | _ = t; |
| 13586 | 13600 | switch (native_os) { |
| ... | ... | @@ -13789,7 +13803,7 @@ fn netLookupUnavailable( |
| 13789 | 13803 | _ = host_name; |
| 13790 | 13804 | _ = options; |
| 13791 | 13805 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| 13792 | resolved.close(ioBasic(t)); | |
| 13806 | resolved.close(io(t)); | |
| 13793 | 13807 | return error.NetworkDown; |
| 13794 | 13808 | } |
| 13795 | 13809 | |
| ... | ... | @@ -14072,7 +14086,7 @@ fn tryLockStderr(userdata: ?*anyopaque, terminal_mode: ?Io.Terminal.Mode) Io.Can |
| 14072 | 14086 | |
| 14073 | 14087 | fn initLockedStderr(t: *Threaded, terminal_mode: ?Io.Terminal.Mode) Io.Cancelable!Io.LockedStderr { |
| 14074 | 14088 | if (!t.stderr_writer_initialized) { |
| 14075 | const io_t = ioBasic(t); | |
| 14089 | const io_t = io(t); | |
| 14076 | 14090 | if (is_windows) t.stderr_writer.file = .stderr(); |
| 14077 | 14091 | t.stderr_writer.io = io_t; |
| 14078 | 14092 | t.stderr_writer_initialized = true; |
lib/std/Io/Uring.zig+22-49| ... | ... | @@ -777,7 +777,6 @@ pub fn io(ev: *Evented) Io { |
| 777 | 777 | .netConnectUnix = netConnectUnixUnavailable, |
| 778 | 778 | .netSocketCreatePair = netSocketCreatePairUnavailable, |
| 779 | 779 | .netSend = netSendUnavailable, |
| 780 | .netReceive = netReceive, | |
| 781 | 780 | .netRead = netReadUnavailable, |
| 782 | 781 | .netWrite = netWriteUnavailable, |
| 783 | 782 | .netWriteFile = netWriteFileUnavailable, |
| ... | ... | @@ -2092,6 +2091,18 @@ fn operate(userdata: ?*anyopaque, operation: Io.Operation) Io.Cancelable!Io.Oper |
| 2092 | 2091 | .device_io_control => |o| .{ |
| 2093 | 2092 | .device_io_control = try ev.deviceIoControl(try maybe_sync.enterSync(ev), o), |
| 2094 | 2093 | }, |
| 2094 | .net_receive => |o| .{ | |
| 2095 | .net_receive = r: { | |
| 2096 | const opt_err, const n = ev.netReceive(&maybe_sync.cancel_region, o.socket_handle, o.message_buffer, o.data_buffer, o.flags); | |
| 2097 | break :r .{ | |
| 2098 | if (opt_err) |err| switch (err) { | |
| 2099 | error.Canceled => |e| return e, | |
| 2100 | else => |e| e, | |
| 2101 | } else null, | |
| 2102 | n, | |
| 2103 | }; | |
| 2104 | }, | |
| 2105 | }, | |
| 2095 | 2106 | }; |
| 2096 | 2107 | } |
| 2097 | 2108 | |
| ... | ... | @@ -2375,6 +2386,10 @@ fn batchDrainSubmitted( |
| 2375 | 2386 | return error.ConcurrencyUnavailable |
| 2376 | 2387 | else |
| 2377 | 2388 | .{ .device_io_control = try ev.deviceIoControl(try maybe_sync.enterSync(ev), o) }, |
| 2389 | .net_receive => |o| { | |
| 2390 | _ = o; | |
| 2391 | @panic("TODO implement batchDrainSubmitted for net_receive"); | |
| 2392 | }, | |
| 2378 | 2393 | })) |result| { |
| 2379 | 2394 | switch (batch.completed.tail) { |
| 2380 | 2395 | .none => batch.completed.head = index, |
| ... | ... | @@ -2475,6 +2490,7 @@ fn batchDrainReady(batch: *Io.Batch) Io.Timeout.Error!void { |
| 2475 | 2490 | }, |
| 2476 | 2491 | }, |
| 2477 | 2492 | .device_io_control => unreachable, |
| 2493 | .net_receive => @panic("TODO"), | |
| 2478 | 2494 | })) |result| { |
| 2479 | 2495 | switch (batch.completed.tail) { |
| 2480 | 2496 | .none => batch.completed.head = index, |
| ... | ... | @@ -5035,37 +5051,16 @@ fn netSendUnavailable( |
| 5035 | 5051 | } |
| 5036 | 5052 | |
| 5037 | 5053 | fn netReceive( |
| 5038 | userdata: ?*anyopaque, | |
| 5054 | ev: *Evented, | |
| 5055 | cancel_region: *CancelRegion, | |
| 5039 | 5056 | handle: net.Socket.Handle, |
| 5040 | 5057 | message_buffer: []net.IncomingMessage, |
| 5041 | 5058 | data_buffer: []u8, |
| 5042 | 5059 | flags: net.ReceiveFlags, |
| 5043 | timeout: Io.Timeout, | |
| 5044 | ) struct { ?net.Socket.ReceiveTimeoutError, usize } { | |
| 5045 | const ev: *Evented = @ptrCast(@alignCast(userdata)); | |
| 5046 | const ev_io = ev.io(); | |
| 5047 | ||
| 5060 | ) struct { ?net.Socket.ReceiveError, usize } { | |
| 5048 | 5061 | var message_i: usize = 0; |
| 5049 | 5062 | var data_i: usize = 0; |
| 5050 | 5063 | |
| 5051 | const deadline: ?struct { | |
| 5052 | raw: Io.Timestamp, | |
| 5053 | timespec: linux.kernel_timespec, | |
| 5054 | clock: Io.Clock, | |
| 5055 | } = if (timeout.toTimestamp(ev_io)) |deadline| deadline: { | |
| 5056 | const ns = deadline.raw.toNanoseconds(); | |
| 5057 | break :deadline .{ | |
| 5058 | .raw = deadline.raw, | |
| 5059 | .timespec = .{ | |
| 5060 | .sec = @intCast(@divFloor(ns, std.time.ns_per_s)), | |
| 5061 | .nsec = @intCast(@mod(ns, std.time.ns_per_s)), | |
| 5062 | }, | |
| 5063 | .clock = deadline.clock, | |
| 5064 | }; | |
| 5065 | } else null; | |
| 5066 | ||
| 5067 | var cancel_region: CancelRegion = .init(); | |
| 5068 | defer cancel_region.deinit(); | |
| 5069 | 5064 | while (true) { |
| 5070 | 5065 | if (message_buffer.len - message_i == 0) return .{ null, message_i }; |
| 5071 | 5066 | const message = &message_buffer[message_i]; |
| ... | ... | @@ -5085,7 +5080,7 @@ fn netReceive( |
| 5085 | 5080 | const thread = cancel_region.awaitIoUring() catch |err| return .{ err, message_i }; |
| 5086 | 5081 | thread.enqueue().* = .{ |
| 5087 | 5082 | .opcode = .RECVMSG, |
| 5088 | .flags = if (deadline) |_| linux.IOSQE_IO_LINK else 0, | |
| 5083 | .flags = 0, | |
| 5089 | 5084 | .ioprio = 0, |
| 5090 | 5085 | .fd = handle, |
| 5091 | 5086 | .off = 0, |
| ... | ... | @@ -5102,26 +5097,6 @@ fn netReceive( |
| 5102 | 5097 | .addr3 = 0, |
| 5103 | 5098 | .resv = 0, |
| 5104 | 5099 | }; |
| 5105 | if (deadline) |*deadline_ptr| thread.enqueue().* = .{ | |
| 5106 | .opcode = .LINK_TIMEOUT, | |
| 5107 | .flags = linux.IOSQE_CQE_SKIP_SUCCESS, | |
| 5108 | .ioprio = 0, | |
| 5109 | .fd = 0, | |
| 5110 | .off = 0, | |
| 5111 | .addr = @intFromPtr(&deadline_ptr.timespec), | |
| 5112 | .len = 1, | |
| 5113 | .rw_flags = linux.IORING_TIMEOUT_ABS | @as(u32, switch (deadline_ptr.clock) { | |
| 5114 | .real => linux.IORING_TIMEOUT_REALTIME, | |
| 5115 | else => 0, | |
| 5116 | .boot => linux.IORING_TIMEOUT_BOOTTIME, | |
| 5117 | }), | |
| 5118 | .user_data = @intFromEnum(Completion.Userdata.wakeup), | |
| 5119 | .buf_index = 0, | |
| 5120 | .personality = 0, | |
| 5121 | .splice_fd_in = 0, | |
| 5122 | .addr3 = 0, | |
| 5123 | .resv = 0, | |
| 5124 | }; | |
| 5125 | 5100 | ev.yield(null, .nothing); |
| 5126 | 5101 | const completion = cancel_region.completion(); |
| 5127 | 5102 | switch (completion.errno()) { |
| ... | ... | @@ -5144,9 +5119,7 @@ fn netReceive( |
| 5144 | 5119 | continue; |
| 5145 | 5120 | }, |
| 5146 | 5121 | .AGAIN => unreachable, |
| 5147 | .INTR, .CANCELED => if (deadline) |d| if (now(ev, d.clock).nanoseconds >= d.raw.nanoseconds) | |
| 5148 | return .{ error.Timeout, message_i }, | |
| 5149 | ||
| 5122 | .INTR, .CANCELED => {}, | |
| 5150 | 5123 | .BADF => |err| return .{ errnoBug(err), message_i }, |
| 5151 | 5124 | .NFILE => return .{ error.SystemFdQuotaExceeded, message_i }, |
| 5152 | 5125 | .MFILE => return .{ error.ProcessFdQuotaExceeded, message_i }, |
lib/std/Io/net.zig+22-28| ... | ... | @@ -1109,25 +1109,7 @@ pub const Socket = struct { |
| 1109 | 1109 | if (n != messages.len) return err.?; |
| 1110 | 1110 | } |
| 1111 | 1111 | |
| 1112 | pub const ReceiveError = error{ | |
| 1113 | /// Insufficient memory or other resource internal to the operating system. | |
| 1114 | SystemResources, | |
| 1115 | /// Per-process limit on the number of open file descriptors has been reached. | |
| 1116 | ProcessFdQuotaExceeded, | |
| 1117 | /// System-wide limit on the total number of open files has been reached. | |
| 1118 | SystemFdQuotaExceeded, | |
| 1119 | /// Local end has been shut down on a connection-oriented socket, or | |
| 1120 | /// the socket was never connected. | |
| 1121 | SocketUnconnected, | |
| 1122 | /// The socket type requires that message be sent atomically, and the | |
| 1123 | /// size of the message to be sent made this impossible. The message | |
| 1124 | /// was not transmitted, or was partially transmitted. | |
| 1125 | MessageOversize, | |
| 1126 | /// Network connection was unexpectedly closed by sender. | |
| 1127 | ConnectionResetByPeer, | |
| 1128 | /// The local network interface used to reach the destination is offline. | |
| 1129 | NetworkDown, | |
| 1130 | } || Io.UnexpectedError || Io.Cancelable; | |
| 1112 | pub const ReceiveError = Io.Operation.NetReceive.Error || Io.Cancelable; | |
| 1131 | 1113 | |
| 1132 | 1114 | /// Waits for data. Connectionless. |
| 1133 | 1115 | /// |
| ... | ... | @@ -1135,17 +1117,18 @@ pub const Socket = struct { |
| 1135 | 1117 | /// * `receiveTimeout` |
| 1136 | 1118 | pub fn receive(s: *const Socket, io: Io, buffer: []u8) ReceiveError!IncomingMessage { |
| 1137 | 1119 | var message: IncomingMessage = .init; |
| 1138 | const maybe_err, const count = io.vtable.netReceive(io.userdata, s.handle, (&message)[0..1], buffer, .{}, .none); | |
| 1139 | if (maybe_err) |err| switch (err) { | |
| 1140 | // No timeout is passed to `netReceieve`, so it must not return timeout related errors. | |
| 1141 | error.Timeout => unreachable, | |
| 1142 | else => |e| return e, | |
| 1143 | }; | |
| 1120 | const maybe_err, const count = (try io.operate(.{ .net_receive = .{ | |
| 1121 | .socket_handle = s.handle, | |
| 1122 | .message_buffer = (&message)[0..1], | |
| 1123 | .data_buffer = buffer, | |
| 1124 | .flags = .{}, | |
| 1125 | } })).net_receive; | |
| 1126 | if (maybe_err) |err| return err; | |
| 1144 | 1127 | assert(1 == count); |
| 1145 | 1128 | return message; |
| 1146 | 1129 | } |
| 1147 | 1130 | |
| 1148 | pub const ReceiveTimeoutError = ReceiveError || Io.Timeout.Error; | |
| 1131 | pub const ReceiveTimeoutError = ReceiveError || Io.Timeout.Error || Io.ConcurrentError; | |
| 1149 | 1132 | |
| 1150 | 1133 | /// Waits for data. Connectionless. |
| 1151 | 1134 | /// |
| ... | ... | @@ -1161,7 +1144,12 @@ pub const Socket = struct { |
| 1161 | 1144 | timeout: Io.Timeout, |
| 1162 | 1145 | ) ReceiveTimeoutError!IncomingMessage { |
| 1163 | 1146 | var message: IncomingMessage = .init; |
| 1164 | const maybe_err, const count = io.vtable.netReceive(io.userdata, s.handle, (&message)[0..1], buffer, .{}, timeout); | |
| 1147 | const maybe_err, const count = (try io.operateTimeout(.{ .net_receive = .{ | |
| 1148 | .socket_handle = s.handle, | |
| 1149 | .message_buffer = (&message)[0..1], | |
| 1150 | .data_buffer = buffer, | |
| 1151 | .flags = .{}, | |
| 1152 | } }, timeout)).net_receive; | |
| 1165 | 1153 | if (maybe_err) |err| return err; |
| 1166 | 1154 | assert(1 == count); |
| 1167 | 1155 | return message; |
| ... | ... | @@ -1186,7 +1174,13 @@ pub const Socket = struct { |
| 1186 | 1174 | flags: ReceiveFlags, |
| 1187 | 1175 | timeout: Io.Timeout, |
| 1188 | 1176 | ) struct { ?ReceiveTimeoutError, usize } { |
| 1189 | return io.vtable.netReceive(io.userdata, s.handle, message_buffer, data_buffer, flags, timeout); | |
| 1177 | const result = io.operateTimeout(.{ .net_receive = .{ | |
| 1178 | .socket_handle = s.handle, | |
| 1179 | .message_buffer = message_buffer, | |
| 1180 | .data_buffer = data_buffer, | |
| 1181 | .flags = flags, | |
| 1182 | } }, timeout) catch |err| return .{ err, 0 }; | |
| 1183 | return result.net_receive; | |
| 1190 | 1184 | } |
| 1191 | 1185 | |
| 1192 | 1186 | pub const CreatePairError = error{ |
lib/std/os/windows/ws2_32.zig+14-11| ... | ... | @@ -661,17 +661,20 @@ pub const IOC_OUT = 1073741824; |
| 661 | 661 | pub const IOC_IN = 2147483648; |
| 662 | 662 | |
| 663 | 663 | pub const MSG = struct { |
| 664 | pub const TRUNC = 256; | |
| 665 | pub const CTRUNC = 512; | |
| 666 | pub const BCAST = 1024; | |
| 667 | pub const MCAST = 2048; | |
| 668 | pub const ERRQUEUE = 4096; | |
| 669 | ||
| 670 | pub const PEEK = 2; | |
| 671 | pub const WAITALL = 8; | |
| 672 | pub const PUSH_IMMEDIATE = 32; | |
| 673 | pub const PARTIAL = 32768; | |
| 674 | pub const INTERRUPT = 16; | |
| 664 | pub const OOB = 0x1; | |
| 665 | pub const PEEK = 0x2; | |
| 666 | pub const DONTROUTE = 0x4; | |
| 667 | pub const WAITALL = 0x8; | |
| 668 | pub const INTERRUPT = 0x10; | |
| 669 | pub const PUSH_IMMEDIATE = 0x20; | |
| 670 | ||
| 671 | pub const TRUNC = 0x0100; | |
| 672 | pub const CTRUNC = 0x0200; | |
| 673 | pub const BCAST = 0x0400; | |
| 674 | pub const MCAST = 0x0800; | |
| 675 | ||
| 676 | pub const PARTIAL = 0x8000; | |
| 677 | ||
| 675 | 678 | pub const MAXIOVLEN = 16; |
| 676 | 679 | }; |
| 677 | 680 |
lib/std/std.zig+4-1| ... | ... | @@ -174,6 +174,9 @@ pub const Options = struct { |
| 174 | 174 | /// stack traces will just print an error to the relevant `Io.Writer` and return. |
| 175 | 175 | allow_stack_tracing: bool = !@import("builtin").strip_debug_info, |
| 176 | 176 | |
| 177 | /// Allows disabling networking in std.Io implementations. | |
| 178 | networking: bool = true, | |
| 179 | ||
| 177 | 180 | /// TODO This is a separate decl instead of a field as a workaround around |
| 178 | 181 | /// compilation errors due to zig not being lazy enough. |
| 179 | 182 | pub const logTerminalMode: fn () Io.Terminal.Mode = log.defaultTerminalMode; |
| ... | ... | @@ -202,7 +205,7 @@ pub const Options = struct { |
| 202 | 205 | /// implementation based on coroutines, one likely wants `std.debug.print` |
| 203 | 206 | /// to directly write to stderr without trying to interact with the code |
| 204 | 207 | /// being debugged. |
| 205 | pub const debug_io: Io = if (@hasDecl(root, "std_options_debug_io")) root.std_options_debug_io else debug_threaded_io.?.ioBasic(); | |
| 208 | pub const debug_io: Io = if (@hasDecl(root, "std_options_debug_io")) root.std_options_debug_io else debug_threaded_io.?.io(); | |
| 206 | 209 | |
| 207 | 210 | /// Overrides `std.Io.File.Permissions`. |
| 208 | 211 | pub const FilePermissions: ?type = if (@hasDecl(root, "std_options_FilePermissions")) root.std_options_FilePermissions else null; |
lib/ubsan_rt.zig+4| ... | ... | @@ -3,6 +3,10 @@ const builtin = @import("builtin"); |
| 3 | 3 | const assert = std.debug.assert; |
| 4 | 4 | const panic = std.debug.panicExtra; |
| 5 | 5 | |
| 6 | pub const std_options: std.Options = .{ | |
| 7 | .networking = false, | |
| 8 | }; | |
| 9 | ||
| 6 | 10 | const SourceLocation = extern struct { |
| 7 | 11 | file_name: ?[*:0]const u8, |
| 8 | 12 | line: u32, |
test/incremental/add_decl+6-6| ... | ... | @@ -10,7 +10,7 @@ pub fn main() !void { |
| 10 | 10 | try std.Io.File.stdout().writeStreamingAll(io, foo); |
| 11 | 11 | } |
| 12 | 12 | const foo = "good morning\n"; |
| 13 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | |
| 13 | const io = std.Io.Threaded.global_single_threaded.io(); | |
| 14 | 14 | #expect_stdout="good morning\n" |
| 15 | 15 | |
| 16 | 16 | #update=add new declaration |
| ... | ... | @@ -21,7 +21,7 @@ pub fn main() !void { |
| 21 | 21 | } |
| 22 | 22 | const foo = "good morning\n"; |
| 23 | 23 | const bar = "good evening\n"; |
| 24 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | |
| 24 | const io = std.Io.Threaded.global_single_threaded.io(); | |
| 25 | 25 | #expect_stdout="good morning\n" |
| 26 | 26 | |
| 27 | 27 | #update=reference new declaration |
| ... | ... | @@ -32,7 +32,7 @@ pub fn main() !void { |
| 32 | 32 | } |
| 33 | 33 | const foo = "good morning\n"; |
| 34 | 34 | const bar = "good evening\n"; |
| 35 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | |
| 35 | const io = std.Io.Threaded.global_single_threaded.io(); | |
| 36 | 36 | #expect_stdout="good evening\n" |
| 37 | 37 | |
| 38 | 38 | #update=reference missing declaration |
| ... | ... | @@ -43,7 +43,7 @@ pub fn main() !void { |
| 43 | 43 | } |
| 44 | 44 | const foo = "good morning\n"; |
| 45 | 45 | const bar = "good evening\n"; |
| 46 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | |
| 46 | const io = std.Io.Threaded.global_single_threaded.io(); | |
| 47 | 47 | #expect_error=main.zig:3:52: error: use of undeclared identifier 'qux' |
| 48 | 48 | |
| 49 | 49 | #update=add missing declaration |
| ... | ... | @@ -55,7 +55,7 @@ pub fn main() !void { |
| 55 | 55 | const foo = "good morning\n"; |
| 56 | 56 | const bar = "good evening\n"; |
| 57 | 57 | const qux = "good night\n"; |
| 58 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | |
| 58 | const io = std.Io.Threaded.global_single_threaded.io(); | |
| 59 | 59 | #expect_stdout="good night\n" |
| 60 | 60 | |
| 61 | 61 | #update=remove unused declarations |
| ... | ... | @@ -65,5 +65,5 @@ pub fn main() !void { |
| 65 | 65 | try std.Io.File.stdout().writeStreamingAll(io, qux); |
| 66 | 66 | } |
| 67 | 67 | const qux = "good night\n"; |
| 68 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | |
| 68 | const io = std.Io.Threaded.global_single_threaded.io(); | |
| 69 | 69 | #expect_stdout="good night\n" |
test/incremental/add_decl_namespaced+6-6| ... | ... | @@ -10,7 +10,7 @@ pub fn main() !void { |
| 10 | 10 | try std.Io.File.stdout().writeStreamingAll(io, @This().foo); |
| 11 | 11 | } |
| 12 | 12 | const foo = "good morning\n"; |
| 13 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | |
| 13 | const io = std.Io.Threaded.global_single_threaded.io(); | |
| 14 | 14 | #expect_stdout="good morning\n" |
| 15 | 15 | |
| 16 | 16 | #update=add new declaration |
| ... | ... | @@ -21,7 +21,7 @@ pub fn main() !void { |
| 21 | 21 | } |
| 22 | 22 | const foo = "good morning\n"; |
| 23 | 23 | const bar = "good evening\n"; |
| 24 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | |
| 24 | const io = std.Io.Threaded.global_single_threaded.io(); | |
| 25 | 25 | #expect_stdout="good morning\n" |
| 26 | 26 | |
| 27 | 27 | #update=reference new declaration |
| ... | ... | @@ -32,7 +32,7 @@ pub fn main() !void { |
| 32 | 32 | } |
| 33 | 33 | const foo = "good morning\n"; |
| 34 | 34 | const bar = "good evening\n"; |
| 35 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | |
| 35 | const io = std.Io.Threaded.global_single_threaded.io(); | |
| 36 | 36 | #expect_stdout="good evening\n" |
| 37 | 37 | |
| 38 | 38 | #update=reference missing declaration |
| ... | ... | @@ -43,7 +43,7 @@ pub fn main() !void { |
| 43 | 43 | } |
| 44 | 44 | const foo = "good morning\n"; |
| 45 | 45 | const bar = "good evening\n"; |
| 46 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | |
| 46 | const io = std.Io.Threaded.global_single_threaded.io(); | |
| 47 | 47 | #expect_error=main.zig:3:59: error: root source file struct 'main' has no member named 'qux' |
| 48 | 48 | #expect_error=main.zig:1:1: note: struct declared here |
| 49 | 49 | |
| ... | ... | @@ -56,7 +56,7 @@ pub fn main() !void { |
| 56 | 56 | const foo = "good morning\n"; |
| 57 | 57 | const bar = "good evening\n"; |
| 58 | 58 | const qux = "good night\n"; |
| 59 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | |
| 59 | const io = std.Io.Threaded.global_single_threaded.io(); | |
| 60 | 60 | #expect_stdout="good night\n" |
| 61 | 61 | |
| 62 | 62 | #update=remove unused declarations |
| ... | ... | @@ -66,5 +66,5 @@ pub fn main() !void { |
| 66 | 66 | try std.Io.File.stdout().writeStreamingAll(io, @This().qux); |
| 67 | 67 | } |
| 68 | 68 | const qux = "good night\n"; |
| 69 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | |
| 69 | const io = std.Io.Threaded.global_single_threaded.io(); | |
| 70 | 70 | #expect_stdout="good night\n" |
test/incremental/bad_import+2-2| ... | ... | @@ -11,7 +11,7 @@ pub fn main() !void { |
| 11 | 11 | try std.Io.File.stdout().writeStreamingAll(io, "success\n"); |
| 12 | 12 | } |
| 13 | 13 | const std = @import("std"); |
| 14 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | |
| 14 | const io = std.Io.Threaded.global_single_threaded.io(); | |
| 15 | 15 | #file=foo.zig |
| 16 | 16 | comptime { |
| 17 | 17 | _ = @import("bad.zig"); |
| ... | ... | @@ -34,5 +34,5 @@ pub fn main() !void { |
| 34 | 34 | try std.Io.File.stdout().writeStreamingAll(io, "success\n"); |
| 35 | 35 | } |
| 36 | 36 | const std = @import("std"); |
| 37 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | |
| 37 | const io = std.Io.Threaded.global_single_threaded.io(); | |
| 38 | 38 | #expect_stdout="success\n" |
test/incremental/change_embed_file+3-3| ... | ... | @@ -10,7 +10,7 @@ const string = @embedFile("string.txt"); |
| 10 | 10 | pub fn main() !void { |
| 11 | 11 | try std.Io.File.stdout().writeStreamingAll(io, string); |
| 12 | 12 | } |
| 13 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | |
| 13 | const io = std.Io.Threaded.global_single_threaded.io(); | |
| 14 | 14 | #file=string.txt |
| 15 | 15 | Hello, World! |
| 16 | 16 | #expect_stdout="Hello, World!\n" |
| ... | ... | @@ -31,7 +31,7 @@ const string = @embedFile("string.txt"); |
| 31 | 31 | pub fn main() !void { |
| 32 | 32 | try std.Io.File.stdout().writeStreamingAll(io, "a hardcoded string\n"); |
| 33 | 33 | } |
| 34 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | |
| 34 | const io = std.Io.Threaded.global_single_threaded.io(); | |
| 35 | 35 | #expect_stdout="a hardcoded string\n" |
| 36 | 36 | |
| 37 | 37 | #update=re-introduce reference to file |
| ... | ... | @@ -41,7 +41,7 @@ const string = @embedFile("string.txt"); |
| 41 | 41 | pub fn main() !void { |
| 42 | 42 | try std.Io.File.stdout().writeStreamingAll(io, string); |
| 43 | 43 | } |
| 44 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | |
| 44 | const io = std.Io.Threaded.global_single_threaded.io(); | |
| 45 | 45 | #expect_error=main.zig:2:27: error: unable to open 'string.txt': FileNotFound |
| 46 | 46 | |
| 47 | 47 | #update=recreate file |
test/incremental/change_enum_tag_type+3-3| ... | ... | @@ -19,7 +19,7 @@ pub fn main() !void { |
| 19 | 19 | try stdout_writer.interface.print("{s}\n", .{@tagName(val)}); |
| 20 | 20 | } |
| 21 | 21 | const std = @import("std"); |
| 22 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | |
| 22 | const io = std.Io.Threaded.global_single_threaded.io(); | |
| 23 | 23 | #expect_stdout="a\n" |
| 24 | 24 | #update=too many enum fields |
| 25 | 25 | #file=main.zig |
| ... | ... | @@ -43,7 +43,7 @@ comptime { |
| 43 | 43 | std.debug.assert(@TypeOf(@intFromEnum(Foo.e)) == Tag); |
| 44 | 44 | } |
| 45 | 45 | const std = @import("std"); |
| 46 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | |
| 46 | const io = std.Io.Threaded.global_single_threaded.io(); | |
| 47 | 47 | #expect_error=main.zig:7:5: error: enumeration value '4' too large for type 'u2' |
| 48 | 48 | #update=increase tag size |
| 49 | 49 | #file=main.zig |
| ... | ... | @@ -62,5 +62,5 @@ pub fn main() !void { |
| 62 | 62 | try stdout_writer.interface.print("{s}\n", .{@tagName(val)}); |
| 63 | 63 | } |
| 64 | 64 | const std = @import("std"); |
| 65 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | |
| 65 | const io = std.Io.Threaded.global_single_threaded.io(); | |
| 66 | 66 | #expect_stdout="a\n" |
test/incremental/change_exports+6-6| ... | ... | @@ -21,7 +21,7 @@ pub fn main() !void { |
| 21 | 21 | try stdout_writer.interface.print("{}\n", .{S.bar}); |
| 22 | 22 | } |
| 23 | 23 | const std = @import("std"); |
| 24 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | |
| 24 | const io = std.Io.Threaded.global_single_threaded.io(); | |
| 25 | 25 | #expect_stdout="123\n" |
| 26 | 26 | |
| 27 | 27 | #update=add conflict |
| ... | ... | @@ -44,7 +44,7 @@ pub fn main() !void { |
| 44 | 44 | try stdout_writer.interface.print("{} {}\n", .{ S.bar, S.other }); |
| 45 | 45 | } |
| 46 | 46 | const std = @import("std"); |
| 47 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | |
| 47 | const io = std.Io.Threaded.global_single_threaded.io(); | |
| 48 | 48 | #expect_error=main.zig:6:5: error: exported symbol collision: foo |
| 49 | 49 | #expect_error=main.zig:1:1: note: other symbol here |
| 50 | 50 | |
| ... | ... | @@ -68,7 +68,7 @@ pub fn main() !void { |
| 68 | 68 | try stdout_writer.interface.print("{} {}\n", .{ S.bar, S.other }); |
| 69 | 69 | } |
| 70 | 70 | const std = @import("std"); |
| 71 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | |
| 71 | const io = std.Io.Threaded.global_single_threaded.io(); | |
| 72 | 72 | #expect_stdout="123 456\n" |
| 73 | 73 | |
| 74 | 74 | #update=put exports in decl |
| ... | ... | @@ -94,7 +94,7 @@ pub fn main() !void { |
| 94 | 94 | try stdout_writer.interface.print("{} {}\n", .{ S.bar, S.other }); |
| 95 | 95 | } |
| 96 | 96 | const std = @import("std"); |
| 97 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | |
| 97 | const io = std.Io.Threaded.global_single_threaded.io(); | |
| 98 | 98 | #expect_stdout="123 456\n" |
| 99 | 99 | |
| 100 | 100 | #update=remove reference to exporting decl |
| ... | ... | @@ -141,7 +141,7 @@ pub fn main() !void { |
| 141 | 141 | try stdout_writer.interface.print("{} {}\n", .{ S.bar, S.other }); |
| 142 | 142 | } |
| 143 | 143 | const std = @import("std"); |
| 144 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | |
| 144 | const io = std.Io.Threaded.global_single_threaded.io(); | |
| 145 | 145 | #expect_stdout="123 456\n" |
| 146 | 146 | |
| 147 | 147 | #update=reintroduce reference to exporting decl, introducing conflict |
| ... | ... | @@ -167,7 +167,7 @@ pub fn main() !void { |
| 167 | 167 | try stdout_writer.interface.print("{} {}\n", .{ S.bar, S.other }); |
| 168 | 168 | } |
| 169 | 169 | const std = @import("std"); |
| 170 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | |
| 170 | const io = std.Io.Threaded.global_single_threaded.io(); | |
| 171 | 171 | #expect_error=main.zig:5:5: error: exported symbol collision: bar |
| 172 | 172 | #expect_error=main.zig:2:1: note: other symbol here |
| 173 | 173 | #expect_error=main.zig:6:5: error: exported symbol collision: other |
test/incremental/change_fn_type+3-3| ... | ... | @@ -12,7 +12,7 @@ fn foo(x: u8) !void { |
| 12 | 12 | return stdout_writer.interface.print("{d}\n", .{x}); |
| 13 | 13 | } |
| 14 | 14 | const std = @import("std"); |
| 15 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | |
| 15 | const io = std.Io.Threaded.global_single_threaded.io(); | |
| 16 | 16 | #expect_stdout="123\n" |
| 17 | 17 | |
| 18 | 18 | #update=change function type |
| ... | ... | @@ -25,7 +25,7 @@ fn foo(x: i64) !void { |
| 25 | 25 | return stdout_writer.interface.print("{d}\n", .{x}); |
| 26 | 26 | } |
| 27 | 27 | const std = @import("std"); |
| 28 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | |
| 28 | const io = std.Io.Threaded.global_single_threaded.io(); | |
| 29 | 29 | #expect_stdout="123\n" |
| 30 | 30 | |
| 31 | 31 | #update=change function argument |
| ... | ... | @@ -38,5 +38,5 @@ fn foo(x: i64) !void { |
| 38 | 38 | return stdout_writer.interface.print("{d}\n", .{x}); |
| 39 | 39 | } |
| 40 | 40 | const std = @import("std"); |
| 41 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | |
| 41 | const io = std.Io.Threaded.global_single_threaded.io(); | |
| 42 | 42 | #expect_stdout="-42\n" |
test/incremental/change_generic_line_number+2-2| ... | ... | @@ -4,7 +4,7 @@ |
| 4 | 4 | #update=initial version |
| 5 | 5 | #file=main.zig |
| 6 | 6 | const std = @import("std"); |
| 7 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | |
| 7 | const io = std.Io.Threaded.global_single_threaded.io(); | |
| 8 | 8 | fn Printer(message: []const u8) type { |
| 9 | 9 | return struct { |
| 10 | 10 | fn print() !void { |
| ... | ... | @@ -20,7 +20,7 @@ pub fn main() !void { |
| 20 | 20 | #update=change line number |
| 21 | 21 | #file=main.zig |
| 22 | 22 | const std = @import("std"); |
| 23 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | |
| 23 | const io = std.Io.Threaded.global_single_threaded.io(); | |
| 24 | 24 | |
| 25 | 25 | fn Printer(message: []const u8) type { |
| 26 | 26 | return struct { |
test/incremental/change_line_number+2-2| ... | ... | @@ -7,7 +7,7 @@ const std = @import("std"); |
| 7 | 7 | pub fn main() !void { |
| 8 | 8 | try std.Io.File.stdout().writeStreamingAll(io, "foo\n"); |
| 9 | 9 | } |
| 10 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | |
| 10 | const io = std.Io.Threaded.global_single_threaded.io(); | |
| 11 | 11 | #expect_stdout="foo\n" |
| 12 | 12 | #update=change line number |
| 13 | 13 | #file=main.zig |
| ... | ... | @@ -16,5 +16,5 @@ const std = @import("std"); |
| 16 | 16 | pub fn main() !void { |
| 17 | 17 | try std.Io.File.stdout().writeStreamingAll(io, "foo\n"); |
| 18 | 18 | } |
| 19 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | |
| 19 | const io = std.Io.Threaded.global_single_threaded.io(); | |
| 20 | 20 | #expect_stdout="foo\n" |
test/incremental/change_panic_handler+3-3| ... | ... | @@ -17,7 +17,7 @@ fn myPanic(msg: []const u8, _: ?usize) noreturn { |
| 17 | 17 | std.process.exit(0); |
| 18 | 18 | } |
| 19 | 19 | const std = @import("std"); |
| 20 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | |
| 20 | const io = std.Io.Threaded.global_single_threaded.io(); | |
| 21 | 21 | #expect_stdout="panic message: integer overflow\n" |
| 22 | 22 | |
| 23 | 23 | #update=change the panic handler body |
| ... | ... | @@ -35,7 +35,7 @@ fn myPanic(msg: []const u8, _: ?usize) noreturn { |
| 35 | 35 | std.process.exit(0); |
| 36 | 36 | } |
| 37 | 37 | const std = @import("std"); |
| 38 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | |
| 38 | const io = std.Io.Threaded.global_single_threaded.io(); | |
| 39 | 39 | #expect_stdout="new panic message: integer overflow\n" |
| 40 | 40 | |
| 41 | 41 | #update=change the panic handler function value |
| ... | ... | @@ -53,5 +53,5 @@ fn myPanicNew(msg: []const u8, _: ?usize) noreturn { |
| 53 | 53 | std.process.exit(0); |
| 54 | 54 | } |
| 55 | 55 | const std = @import("std"); |
| 56 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | |
| 56 | const io = std.Io.Threaded.global_single_threaded.io(); | |
| 57 | 57 | #expect_stdout="third panic message: integer overflow\n" |
test/incremental/change_panic_handler_explicit+3-3| ... | ... | @@ -47,7 +47,7 @@ fn myPanic(msg: []const u8, _: ?usize) noreturn { |
| 47 | 47 | std.process.exit(0); |
| 48 | 48 | } |
| 49 | 49 | const std = @import("std"); |
| 50 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | |
| 50 | const io = std.Io.Threaded.global_single_threaded.io(); | |
| 51 | 51 | #expect_stdout="panic message: integer overflow\n" |
| 52 | 52 | |
| 53 | 53 | #update=change the panic handler body |
| ... | ... | @@ -95,7 +95,7 @@ fn myPanic(msg: []const u8, _: ?usize) noreturn { |
| 95 | 95 | std.process.exit(0); |
| 96 | 96 | } |
| 97 | 97 | const std = @import("std"); |
| 98 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | |
| 98 | const io = std.Io.Threaded.global_single_threaded.io(); | |
| 99 | 99 | #expect_stdout="new panic message: integer overflow\n" |
| 100 | 100 | |
| 101 | 101 | #update=change the panic handler function value |
| ... | ... | @@ -143,5 +143,5 @@ fn myPanicNew(msg: []const u8, _: ?usize) noreturn { |
| 143 | 143 | std.process.exit(0); |
| 144 | 144 | } |
| 145 | 145 | const std = @import("std"); |
| 146 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | |
| 146 | const io = std.Io.Threaded.global_single_threaded.io(); | |
| 147 | 147 | #expect_stdout="third panic message: integer overflow\n" |
test/incremental/change_shift_op+2-2| ... | ... | @@ -13,7 +13,7 @@ fn foo(x: u16) !void { |
| 13 | 13 | try stdout_writer.interface.print("0x{x}\n", .{x << 4}); |
| 14 | 14 | } |
| 15 | 15 | const std = @import("std"); |
| 16 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | |
| 16 | const io = std.Io.Threaded.global_single_threaded.io(); | |
| 17 | 17 | #expect_stdout="0x3000\n" |
| 18 | 18 | #update=change to right shift |
| 19 | 19 | #file=main.zig |
| ... | ... | @@ -25,5 +25,5 @@ fn foo(x: u16) !void { |
| 25 | 25 | try stdout_writer.interface.print("0x{x}\n", .{x >> 4}); |
| 26 | 26 | } |
| 27 | 27 | const std = @import("std"); |
| 28 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | |
| 28 | const io = std.Io.Threaded.global_single_threaded.io(); | |
| 29 | 29 | #expect_stdout="0x130\n" |
test/incremental/change_struct_same_fields+3-3| ... | ... | @@ -18,7 +18,7 @@ fn foo(val: *const S) !void { |
| 18 | 18 | ); |
| 19 | 19 | } |
| 20 | 20 | const std = @import("std"); |
| 21 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | |
| 21 | const io = std.Io.Threaded.global_single_threaded.io(); | |
| 22 | 22 | #expect_stdout="100 200\n" |
| 23 | 23 | |
| 24 | 24 | #update=change struct layout |
| ... | ... | @@ -36,7 +36,7 @@ fn foo(val: *const S) !void { |
| 36 | 36 | ); |
| 37 | 37 | } |
| 38 | 38 | const std = @import("std"); |
| 39 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | |
| 39 | const io = std.Io.Threaded.global_single_threaded.io(); | |
| 40 | 40 | #expect_stdout="100 200\n" |
| 41 | 41 | |
| 42 | 42 | #update=change values |
| ... | ... | @@ -54,5 +54,5 @@ fn foo(val: *const S) !void { |
| 54 | 54 | ); |
| 55 | 55 | } |
| 56 | 56 | const std = @import("std"); |
| 57 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | |
| 57 | const io = std.Io.Threaded.global_single_threaded.io(); | |
| 58 | 58 | #expect_stdout="1234 5678\n" |
test/incremental/change_zon_file+3-3| ... | ... | @@ -10,7 +10,7 @@ const message: []const u8 = @import("message.zon"); |
| 10 | 10 | pub fn main() !void { |
| 11 | 11 | try std.Io.File.stdout().writeStreamingAll(io, message); |
| 12 | 12 | } |
| 13 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | |
| 13 | const io = std.Io.Threaded.global_single_threaded.io(); | |
| 14 | 14 | #file=message.zon |
| 15 | 15 | "Hello, World!\n" |
| 16 | 16 | #expect_stdout="Hello, World!\n" |
| ... | ... | @@ -32,7 +32,7 @@ const message: []const u8 = @import("message.zon"); |
| 32 | 32 | pub fn main() !void { |
| 33 | 33 | try std.Io.File.stdout().writeStreamingAll(io, "a hardcoded string\n"); |
| 34 | 34 | } |
| 35 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | |
| 35 | const io = std.Io.Threaded.global_single_threaded.io(); | |
| 36 | 36 | #expect_error=message.zon:1:1: error: unable to load 'message.zon': FileNotFound |
| 37 | 37 | #expect_error=main.zig:2:37: note: file imported here |
| 38 | 38 | |
| ... | ... | @@ -48,5 +48,5 @@ const message: []const u8 = @import("message.zon"); |
| 48 | 48 | pub fn main() !void { |
| 49 | 49 | try std.Io.File.stdout().writeStreamingAll(io, message); |
| 50 | 50 | } |
| 51 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | |
| 51 | const io = std.Io.Threaded.global_single_threaded.io(); | |
| 52 | 52 | #expect_stdout="We're back, World!\n" |
test/incremental/change_zon_file_no_result_type+1-1| ... | ... | @@ -6,7 +6,7 @@ |
| 6 | 6 | #update=initial version |
| 7 | 7 | #file=main.zig |
| 8 | 8 | const std = @import("std"); |
| 9 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | |
| 9 | const io = std.Io.Threaded.global_single_threaded.io(); | |
| 10 | 10 | pub fn main() !void { |
| 11 | 11 | try std.Io.File.stdout().writeStreamingAll(io, @import("foo.zon").message); |
| 12 | 12 | } |
test/incremental/compile_log+3-3| ... | ... | @@ -10,7 +10,7 @@ const std = @import("std"); |
| 10 | 10 | pub fn main() !void { |
| 11 | 11 | try std.Io.File.stdout().writeStreamingAll(io, "Hello, World!\n"); |
| 12 | 12 | } |
| 13 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | |
| 13 | const io = std.Io.Threaded.global_single_threaded.io(); | |
| 14 | 14 | #expect_stdout="Hello, World!\n" |
| 15 | 15 | |
| 16 | 16 | #update=add compile log |
| ... | ... | @@ -20,7 +20,7 @@ pub fn main() !void { |
| 20 | 20 | try std.Io.File.stdout().writeStreamingAll(io, "Hello, World!\n"); |
| 21 | 21 | @compileLog("this is a log"); |
| 22 | 22 | } |
| 23 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | |
| 23 | const io = std.Io.Threaded.global_single_threaded.io(); | |
| 24 | 24 | #expect_error=main.zig:4:5: error: found compile log statement |
| 25 | 25 | #expect_compile_log=@as(*const [13:0]u8, "this is a log") |
| 26 | 26 | |
| ... | ... | @@ -30,5 +30,5 @@ const std = @import("std"); |
| 30 | 30 | pub fn main() !void { |
| 31 | 31 | try std.Io.File.stdout().writeStreamingAll(io, "Hello, World!\n"); |
| 32 | 32 | } |
| 33 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | |
| 33 | const io = std.Io.Threaded.global_single_threaded.io(); | |
| 34 | 34 | #expect_stdout="Hello, World!\n" |
test/incremental/fix_astgen_failure+3-3| ... | ... | @@ -19,7 +19,7 @@ const std = @import("std"); |
| 19 | 19 | pub fn hello() !void { |
| 20 | 20 | try std.Io.File.stdout().writeStreamingAll(io, "Hello, World!\n"); |
| 21 | 21 | } |
| 22 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | |
| 22 | const io = std.Io.Threaded.global_single_threaded.io(); | |
| 23 | 23 | #expect_stdout="Hello, World!\n" |
| 24 | 24 | #update=add new error |
| 25 | 25 | #file=foo.zig |
| ... | ... | @@ -27,7 +27,7 @@ const std = @import("std"); |
| 27 | 27 | pub fn hello() !void { |
| 28 | 28 | try std.Io.File.stdout().writeStreamingAll(io, hello_str); |
| 29 | 29 | } |
| 30 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | |
| 30 | const io = std.Io.Threaded.global_single_threaded.io(); | |
| 31 | 31 | #expect_error=foo.zig:3:52: error: use of undeclared identifier 'hello_str' |
| 32 | 32 | #update=fix the new error |
| 33 | 33 | #file=foo.zig |
| ... | ... | @@ -36,5 +36,5 @@ const hello_str = "Hello, World! Again!\n"; |
| 36 | 36 | pub fn hello() !void { |
| 37 | 37 | try std.Io.File.stdout().writeStreamingAll(io, hello_str); |
| 38 | 38 | } |
| 39 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | |
| 39 | const io = std.Io.Threaded.global_single_threaded.io(); | |
| 40 | 40 | #expect_stdout="Hello, World! Again!\n" |
test/incremental/function_becomes_inline+3-3| ... | ... | @@ -11,7 +11,7 @@ fn foo() !void { |
| 11 | 11 | try std.Io.File.stdout().writeStreamingAll(io, "Hello, World!\n"); |
| 12 | 12 | } |
| 13 | 13 | const std = @import("std"); |
| 14 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | |
| 14 | const io = std.Io.Threaded.global_single_threaded.io(); | |
| 15 | 15 | #expect_stdout="Hello, World!\n" |
| 16 | 16 | |
| 17 | 17 | #update=make function inline |
| ... | ... | @@ -23,7 +23,7 @@ inline fn foo() !void { |
| 23 | 23 | try std.Io.File.stdout().writeStreamingAll(io, "Hello, World!\n"); |
| 24 | 24 | } |
| 25 | 25 | const std = @import("std"); |
| 26 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | |
| 26 | const io = std.Io.Threaded.global_single_threaded.io(); | |
| 27 | 27 | #expect_stdout="Hello, World!\n" |
| 28 | 28 | |
| 29 | 29 | #update=change string |
| ... | ... | @@ -35,5 +35,5 @@ inline fn foo() !void { |
| 35 | 35 | try std.Io.File.stdout().writeStreamingAll(io, "Hello, `inline` World!\n"); |
| 36 | 36 | } |
| 37 | 37 | const std = @import("std"); |
| 38 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | |
| 38 | const io = std.Io.Threaded.global_single_threaded.io(); | |
| 39 | 39 | #expect_stdout="Hello, `inline` World!\n" |
test/incremental/hello+2-2| ... | ... | @@ -6,7 +6,7 @@ |
| 6 | 6 | #update=initial version |
| 7 | 7 | #file=main.zig |
| 8 | 8 | const std = @import("std"); |
| 9 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | |
| 9 | const io = std.Io.Threaded.global_single_threaded.io(); | |
| 10 | 10 | pub fn main() !void { |
| 11 | 11 | try std.Io.File.stdout().writeStreamingAll(io, "good morning\n"); |
| 12 | 12 | } |
| ... | ... | @@ -14,7 +14,7 @@ pub fn main() !void { |
| 14 | 14 | #update=change the string |
| 15 | 15 | #file=main.zig |
| 16 | 16 | const std = @import("std"); |
| 17 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | |
| 17 | const io = std.Io.Threaded.global_single_threaded.io(); | |
| 18 | 18 | pub fn main() !void { |
| 19 | 19 | try std.Io.File.stdout().writeStreamingAll(io, "おはようございます\n"); |
| 20 | 20 | } |
test/incremental/make_decl_pub+2-2| ... | ... | @@ -14,7 +14,7 @@ const std = @import("std"); |
| 14 | 14 | fn hello() !void { |
| 15 | 15 | try std.Io.File.stdout().writeStreamingAll(io, "Hello, World!\n"); |
| 16 | 16 | } |
| 17 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | |
| 17 | const io = std.Io.Threaded.global_single_threaded.io(); | |
| 18 | 18 | #expect_error=main.zig:3:12: error: 'hello' is not marked 'pub' |
| 19 | 19 | #expect_error=foo.zig:2:1: note: declared here |
| 20 | 20 | |
| ... | ... | @@ -24,5 +24,5 @@ const std = @import("std"); |
| 24 | 24 | pub fn hello() !void { |
| 25 | 25 | try std.Io.File.stdout().writeStreamingAll(io, "Hello, World!\n"); |
| 26 | 26 | } |
| 27 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | |
| 27 | const io = std.Io.Threaded.global_single_threaded.io(); | |
| 28 | 28 | #expect_stdout="Hello, World!\n" |
test/incremental/modify_inline_fn+2-2| ... | ... | @@ -13,7 +13,7 @@ pub fn main() !void { |
| 13 | 13 | inline fn getStr() []const u8 { |
| 14 | 14 | return "foo\n"; |
| 15 | 15 | } |
| 16 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | |
| 16 | const io = std.Io.Threaded.global_single_threaded.io(); | |
| 17 | 17 | #expect_stdout="foo\n" |
| 18 | 18 | #update=change the string |
| 19 | 19 | #file=main.zig |
| ... | ... | @@ -25,5 +25,5 @@ pub fn main() !void { |
| 25 | 25 | inline fn getStr() []const u8 { |
| 26 | 26 | return "bar\n"; |
| 27 | 27 | } |
| 28 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | |
| 28 | const io = std.Io.Threaded.global_single_threaded.io(); | |
| 29 | 29 | #expect_stdout="bar\n" |
test/incremental/move_src+2-2| ... | ... | @@ -16,7 +16,7 @@ fn foo() u32 { |
| 16 | 16 | fn bar() u32 { |
| 17 | 17 | return 123; |
| 18 | 18 | } |
| 19 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | |
| 19 | const io = std.Io.Threaded.global_single_threaded.io(); | |
| 20 | 20 | #expect_stdout="7 123\n" |
| 21 | 21 | |
| 22 | 22 | #update=add newline |
| ... | ... | @@ -33,5 +33,5 @@ fn foo() u32 { |
| 33 | 33 | fn bar() u32 { |
| 34 | 34 | return 123; |
| 35 | 35 | } |
| 36 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | |
| 36 | const io = std.Io.Threaded.global_single_threaded.io(); | |
| 37 | 37 | #expect_stdout="8 123\n" |
test/incremental/no_change_preserves_tag_names+2-2| ... | ... | @@ -7,7 +7,7 @@ |
| 7 | 7 | #file=main.zig |
| 8 | 8 | const std = @import("std"); |
| 9 | 9 | var some_enum: enum { first, second } = .first; |
| 10 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | |
| 10 | const io = std.Io.Threaded.global_single_threaded.io(); | |
| 11 | 11 | pub fn main() !void { |
| 12 | 12 | try std.Io.File.stdout().writeStreamingAll(io, @tagName(some_enum)); |
| 13 | 13 | } |
| ... | ... | @@ -16,7 +16,7 @@ pub fn main() !void { |
| 16 | 16 | #file=main.zig |
| 17 | 17 | const std = @import("std"); |
| 18 | 18 | var some_enum: enum { first, second } = .first; |
| 19 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | |
| 19 | const io = std.Io.Threaded.global_single_threaded.io(); | |
| 20 | 20 | pub fn main() !void { |
| 21 | 21 | try std.Io.File.stdout().writeStreamingAll(io, @tagName(some_enum)); |
| 22 | 22 | } |
test/incremental/recursive_function_becomes_non_recursive+2-2| ... | ... | @@ -14,7 +14,7 @@ fn foo(recurse: bool) !void { |
| 14 | 14 | try stdout.writeStreamingAll(io, "non-recursive path\n"); |
| 15 | 15 | } |
| 16 | 16 | const std = @import("std"); |
| 17 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | |
| 17 | const io = std.Io.Threaded.global_single_threaded.io(); | |
| 18 | 18 | #expect_stdout="non-recursive path\n" |
| 19 | 19 | |
| 20 | 20 | #update=eliminate recursion and change argument |
| ... | ... | @@ -28,5 +28,5 @@ fn foo(recurse: bool) !void { |
| 28 | 28 | try stdout.writeStreamingAll(io, "non-recursive path\n"); |
| 29 | 29 | } |
| 30 | 30 | const std = @import("std"); |
| 31 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | |
| 31 | const io = std.Io.Threaded.global_single_threaded.io(); | |
| 32 | 32 | #expect_stdout="x==1\n" |
test/incremental/remove_enum_field+2-2| ... | ... | @@ -14,7 +14,7 @@ pub fn main() !void { |
| 14 | 14 | try stdout_writer.interface.print("{}\n", .{@intFromEnum(MyEnum.foo)}); |
| 15 | 15 | } |
| 16 | 16 | const std = @import("std"); |
| 17 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | |
| 17 | const io = std.Io.Threaded.global_single_threaded.io(); | |
| 18 | 18 | #expect_stdout="1\n" |
| 19 | 19 | #update=remove enum field |
| 20 | 20 | #file=main.zig |
| ... | ... | @@ -27,6 +27,6 @@ pub fn main() !void { |
| 27 | 27 | try stdout_writer.interface.print("{}\n", .{@intFromEnum(MyEnum.foo)}); |
| 28 | 28 | } |
| 29 | 29 | const std = @import("std"); |
| 30 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | |
| 30 | const io = std.Io.Threaded.global_single_threaded.io(); | |
| 31 | 31 | #expect_error=main.zig:7:69: error: enum 'main.MyEnum' has no member named 'foo' |
| 32 | 32 | #expect_error=main.zig:1:16: note: enum declared here |
test/incremental/unreferenced_error+4-4| ... | ... | @@ -10,7 +10,7 @@ pub fn main() !void { |
| 10 | 10 | try std.Io.File.stdout().writeStreamingAll(io, a); |
| 11 | 11 | } |
| 12 | 12 | const a = "Hello, World!\n"; |
| 13 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | |
| 13 | const io = std.Io.Threaded.global_single_threaded.io(); | |
| 14 | 14 | #expect_stdout="Hello, World!\n" |
| 15 | 15 | |
| 16 | 16 | #update=introduce compile error |
| ... | ... | @@ -20,7 +20,7 @@ pub fn main() !void { |
| 20 | 20 | try std.Io.File.stdout().writeStreamingAll(io, a); |
| 21 | 21 | } |
| 22 | 22 | const a = @compileError("bad a"); |
| 23 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | |
| 23 | const io = std.Io.Threaded.global_single_threaded.io(); | |
| 24 | 24 | #expect_error=main.zig:5:11: error: bad a |
| 25 | 25 | |
| 26 | 26 | #update=remove error reference |
| ... | ... | @@ -31,7 +31,7 @@ pub fn main() !void { |
| 31 | 31 | } |
| 32 | 32 | const a = @compileError("bad a"); |
| 33 | 33 | const b = "Hi there!\n"; |
| 34 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | |
| 34 | const io = std.Io.Threaded.global_single_threaded.io(); | |
| 35 | 35 | #expect_stdout="Hi there!\n" |
| 36 | 36 | |
| 37 | 37 | #update=introduce and remove reference to error |
| ... | ... | @@ -42,5 +42,5 @@ pub fn main() !void { |
| 42 | 42 | } |
| 43 | 43 | const a = "Back to a\n"; |
| 44 | 44 | const b = @compileError("bad b"); |
| 45 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | |
| 45 | const io = std.Io.Threaded.global_single_threaded.io(); | |
| 46 | 46 | #expect_stdout="Back to a\n" |
test/standalone/coff_dwarf/build.zig+3| ... | ... | @@ -46,6 +46,9 @@ pub fn build(b: *std.Build) void { |
| 46 | 46 | lib.root_module.addCSourceFile(.{ .file = b.path("shared_lib.c"), .flags = &.{"-gdwarf"} }); |
| 47 | 47 | exe.root_module.linkLibrary(lib); |
| 48 | 48 | |
| 49 | if (target.result.os.tag == .windows) | |
| 50 | exe.root_module.linkSystemLibrary("ws2_32", .{}); | |
| 51 | ||
| 49 | 52 | const run = b.addRunArtifact(exe); |
| 50 | 53 | run.expectExitCode(0); |
| 51 | 54 | run.skip_foreign_checks = true; |
test/standalone/dirname/exists_in.zig+1-1| ... | ... | @@ -26,7 +26,7 @@ pub fn main(init: std.process.Init) !void { |
| 26 | 26 | return error.BadUsage; |
| 27 | 27 | }; |
| 28 | 28 | |
| 29 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | |
| 29 | const io = std.Io.Threaded.global_single_threaded.io(); | |
| 30 | 30 | |
| 31 | 31 | var dir = try std.Io.Dir.cwd().openDir(io, dir_path, .{}); |
| 32 | 32 | defer dir.close(io); |
test/standalone/dirname/touch.zig+1-1| ... | ... | @@ -21,7 +21,7 @@ pub fn main(init: std.process.Init) !void { |
| 21 | 21 | const dir_path = std.Io.Dir.path.dirname(path) orelse unreachable; |
| 22 | 22 | const basename = std.Io.Dir.path.basename(path); |
| 23 | 23 | |
| 24 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | |
| 24 | const io = std.Io.Threaded.global_single_threaded.io(); | |
| 25 | 25 | |
| 26 | 26 | var dir = try std.Io.Dir.cwd().openDir(io, dir_path, .{}); |
| 27 | 27 | defer dir.close(io); |
test/standalone/issue_5825/build.zig+1| ... | ... | @@ -34,6 +34,7 @@ pub fn build(b: *std.Build) void { |
| 34 | 34 | exe.subsystem = .console; |
| 35 | 35 | exe.root_module.linkSystemLibrary("kernel32", .{}); |
| 36 | 36 | exe.root_module.linkSystemLibrary("ntdll", .{}); |
| 37 | exe.root_module.linkSystemLibrary("ws2_32", .{}); | |
| 37 | 38 | exe.root_module.addObject(obj); |
| 38 | 39 | |
| 39 | 40 | // TODO: actually check the output |
test/standalone/mix_o_files/build.zig+3| ... | ... | @@ -16,6 +16,9 @@ pub fn build(b: *std.Build) void { |
| 16 | 16 | }), |
| 17 | 17 | }); |
| 18 | 18 | |
| 19 | if (target.result.os.tag == .windows) | |
| 20 | obj.root_module.linkSystemLibrary("ws2_32", .{}); | |
| 21 | ||
| 19 | 22 | const exe = b.addExecutable(.{ |
| 20 | 23 | .name = "test", |
| 21 | 24 | .root_module = b.createModule(.{ |
test/standalone/run_cwd/check_file_exists.zig+1-1| ... | ... | @@ -5,7 +5,7 @@ pub fn main(init: std.process.Init) !void { |
| 5 | 5 | if (args.len != 2) return error.BadUsage; |
| 6 | 6 | const path = args[1]; |
| 7 | 7 | |
| 8 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | |
| 8 | const io = std.Io.Threaded.global_single_threaded.io(); | |
| 9 | 9 | |
| 10 | 10 | std.Io.Dir.cwd().access(io, path, .{}) catch return error.AccessFailed; |
| 11 | 11 | } |
test/standalone/shared_library/build.zig+4-1| ... | ... | @@ -5,7 +5,7 @@ pub fn build(b: *std.Build) void { |
| 5 | 5 | b.default_step = test_step; |
| 6 | 6 | |
| 7 | 7 | const optimize: std.builtin.OptimizeMode = .Debug; |
| 8 | const target = b.graph.host; | |
| 8 | const target = b.standardTargetOptions(.{}); | |
| 9 | 9 | |
| 10 | 10 | const exe_names: []const []const u8 = &.{ "test", "test-dync" }; |
| 11 | 11 | const lib_names: []const []const u8 = &.{ "mathtest", "mathtest-dync" }; |
| ... | ... | @@ -24,6 +24,9 @@ pub fn build(b: *std.Build) void { |
| 24 | 24 | }), |
| 25 | 25 | }); |
| 26 | 26 | |
| 27 | if (target.result.os.tag == .windows) | |
| 28 | lib.root_module.linkSystemLibrary("ws2_32", .{}); | |
| 29 | ||
| 27 | 30 | const exe = b.addExecutable(.{ |
| 28 | 31 | .name = exe_name, |
| 29 | 32 | .root_module = b.createModule(.{ |
test/standalone/windows_argv/build.zig+3| ... | ... | @@ -20,6 +20,8 @@ pub fn build(b: *std.Build) !void { |
| 20 | 20 | .optimize = optimize, |
| 21 | 21 | }), |
| 22 | 22 | }); |
| 23 | lib_gnu.root_module.linkSystemLibrary("ws2_32", .{}); | |
| 24 | ||
| 23 | 25 | const verify_gnu = b.addExecutable(.{ |
| 24 | 26 | .name = "verify-gnu", |
| 25 | 27 | .root_module = b.createModule(.{ |
| ... | ... | @@ -101,6 +103,7 @@ pub fn build(b: *std.Build) !void { |
| 101 | 103 | .flags = &.{ "-DUNICODE", "-D_UNICODE" }, |
| 102 | 104 | }); |
| 103 | 105 | verify_msvc.root_module.linkLibrary(lib_msvc); |
| 106 | verify_msvc.root_module.linkSystemLibrary("ws2_32", .{}); | |
| 104 | 107 | verify_msvc.root_module.link_libc = true; |
| 105 | 108 | |
| 106 | 109 | const run_msvc = b.addRunArtifact(fuzz); |