diff options
| author | Andrew Kelley <superjoe30@gmail.com> | 2017-10-15 16:45:43 -0400 |
|---|---|---|
| committer | Andrew Kelley <superjoe30@gmail.com> | 2017-10-15 16:45:43 -0400 |
| commit | fcef7c4bb2f8705774b9d53c8f81a8e74cbcb630 (patch) | |
| tree | 0cc9202dac3d1715d1cd4f02ae899d7a579422a1 /std | |
| parent | bb169a7b36a658ed463787655df54e3f59133d98 (diff) | |
| download | zig-fcef7c4bb2f8705774b9d53c8f81a8e74cbcb630.tar.gz zig-fcef7c4bb2f8705774b9d53c8f81a8e74cbcb630.zip | |
fix std.io.InStream for windows
now we handle PIPE_BROKEN as an EOF
also set up framework for debugging unexpected posix/windows errors
Diffstat (limited to 'std')
| -rw-r--r-- | std/debug.zig | 1 | ||||
| -rw-r--r-- | std/io.zig | 33 | ||||
| -rw-r--r-- | std/net.zig | 1 | ||||
| -rw-r--r-- | std/os/index.zig | 96 | ||||
| -rw-r--r-- | std/os/path.zig | 7 | ||||
| -rw-r--r-- | std/os/windows/util.zig | 15 |
6 files changed, 95 insertions, 58 deletions
diff --git a/std/debug.zig b/std/debug.zig index aef67c315f..24f4be9fe1 100644 --- a/std/debug.zig +++ b/std/debug.zig @@ -11,6 +11,7 @@ error MissingDebugInfo; error InvalidDebugInfo; error UnsupportedDebugInfo; + pub fn assert(ok: bool) { if (!ok) { // In ReleaseFast test mode, we still want assert(false) to crash, so diff --git a/std/io.zig b/std/io.zig index 54cefb804c..124e7714da 100644 --- a/std/io.zig +++ b/std/io.zig @@ -45,17 +45,12 @@ pub var stderr = OutStream { /// bug in the program that called the function. error Invalid; -/// When an Unexpected error occurs, code that emitted the error likely needs -/// a patch to recognize the unexpected case so that it can handle it and emit -/// a more specific error. -error Unexpected; - error DiskQuota; error FileTooBig; error Io; error NoSpaceLeft; error BadPerm; -error PipeFail; +error BrokenPipe; error BadFd; error IsDir; error NotDir; @@ -207,7 +202,10 @@ pub const OutStream = struct { if (self.handle) |handle| return handle; if (system.GetStdHandle(self.handle_id)) |handle| { if (handle == system.INVALID_HANDLE_VALUE) { - return error.Unexpected; + const err = system.GetLastError(); + return switch (err) { + else => os.unexpectedErrorWindows(err), + }; } self.handle = handle; return handle; @@ -292,7 +290,7 @@ pub const InStream = struct { system.EFAULT => unreachable, system.EBADF => return error.BadFd, system.EIO => return error.Io, - else => return error.Unexpected, + else => return os.unexpectedErrorPosix(read_err), } } if (amt_read == 0) return index; @@ -309,12 +307,12 @@ pub const InStream = struct { const err = system.GetLastError(); return switch (err) { system.ERROR.OPERATION_ABORTED => continue, - system.ERROR.BROKEN_PIPE => error.PipeFail, - else => error.Unexpected, + system.ERROR.BROKEN_PIPE => return index, + else => os.unexpectedErrorWindows(err), }; } + if (amt_read == 0) return index; index += amt_read; - if (amt_read < want_read_count) return index; } return index; } else { @@ -374,7 +372,7 @@ pub const InStream = struct { system.EOVERFLOW => error.Unseekable, system.ESPIPE => error.Unseekable, system.ENXIO => error.Unseekable, - else => error.Unexpected, + else => os.unexpectedErrorPosix(err), }; } }, @@ -394,7 +392,7 @@ pub const InStream = struct { system.EOVERFLOW => error.Unseekable, system.ESPIPE => error.Unseekable, system.ENXIO => error.Unseekable, - else => error.Unexpected, + else => os.unexpectedErrorPosix(err), }; } }, @@ -414,7 +412,7 @@ pub const InStream = struct { system.EOVERFLOW => error.Unseekable, system.ESPIPE => error.Unseekable, system.ENXIO => error.Unseekable, - else => error.Unexpected, + else => os.unexpectedErrorPosix(err), }; } return result; @@ -430,7 +428,7 @@ pub const InStream = struct { return switch (err) { system.EBADF => error.BadFd, system.ENOMEM => error.OutOfMemory, - else => error.Unexpected, + else => os.unexpectedErrorPosix(err), } } @@ -485,7 +483,10 @@ pub const InStream = struct { if (self.handle) |handle| return handle; if (system.GetStdHandle(self.handle_id)) |handle| { if (handle == system.INVALID_HANDLE_VALUE) { - return error.Unexpected; + const err = system.GetLastError(); + return switch (err) { + else => os.unexpectedErrorWindows(err), + }; } self.handle = handle; return handle; diff --git a/std/net.zig b/std/net.zig index 1a0bfb6f03..3551499c6b 100644 --- a/std/net.zig +++ b/std/net.zig @@ -3,7 +3,6 @@ const assert = @import("debug.zig").assert; const endian = @import("endian.zig"); error SigInterrupt; -error Unexpected; error Io; error TimedOut; error ConnectionReset; diff --git a/std/os/index.zig b/std/os/index.zig index 5eb3c1b8ef..498c10f518 100644 --- a/std/os/index.zig +++ b/std/os/index.zig @@ -51,7 +51,6 @@ const ArrayList = @import("../array_list.zig").ArrayList; const Buffer = @import("../buffer.zig").Buffer; const math = @import("../index.zig").math; -error Unexpected; error SystemResources; error AccessDenied; error InvalidExe; @@ -81,7 +80,7 @@ pub fn getRandomBytes(buf: []u8) -> %void { posix.EINVAL => unreachable, posix.EFAULT => unreachable, posix.EINTR => continue, - else => error.Unexpected, + else => unexpectedErrorPosix(err), } } return; @@ -96,12 +95,18 @@ pub fn getRandomBytes(buf: []u8) -> %void { Os.windows => { var hCryptProv: windows.HCRYPTPROV = undefined; if (windows.CryptAcquireContextA(&hCryptProv, null, null, windows.PROV_RSA_FULL, 0) == 0) { - return error.Unexpected; + const err = windows.GetLastError(); + return switch (err) { + else => unexpectedErrorWindows(err), + }; } defer _ = windows.CryptReleaseContext(hCryptProv, 0); if (windows.CryptGenRandom(hCryptProv, windows.DWORD(buf.len), buf.ptr) == 0) { - return error.Unexpected; + const err = windows.GetLastError(); + return switch (err) { + else => unexpectedErrorWindows(err), + }; } }, else => @compileError("Unsupported OS"), @@ -187,8 +192,8 @@ pub fn posixRead(fd: i32, buf: []u8) -> %void { posix.EIO => error.InputOutput, posix.EISDIR => error.IsDir, posix.ENOBUFS, posix.ENOMEM => error.SystemResources, - else => return error.Unexpected, - } + else => unexpectedErrorPosix(err), + }; } index += amt_written; } @@ -202,7 +207,6 @@ error FileTooBig; error InputOutput; error NoSpaceLeft; error BrokenPipe; -error Unexpected; /// Calls POSIX write, and keeps trying if it gets interrupted. pub fn posixWrite(fd: i32, bytes: []const u8) -> %void { @@ -222,8 +226,8 @@ pub fn posixWrite(fd: i32, bytes: []const u8) -> %void { posix.ENOSPC => error.NoSpaceLeft, posix.EPERM => error.AccessDenied, posix.EPIPE => error.BrokenPipe, - else => error.Unexpected, - } + else => unexpectedErrorPosix(write_err), + }; } return; } @@ -277,7 +281,7 @@ pub fn posixOpen(file_path: []const u8, flags: u32, perm: usize, allocator: ?&Al posix.ENOTDIR => error.NotDir, posix.EPERM => error.AccessDenied, posix.EEXIST => error.PathAlreadyExists, - else => error.Unexpected, + else => unexpectedErrorPosix(err), } } return i32(result); @@ -292,7 +296,7 @@ pub fn posixDup2(old_fd: i32, new_fd: i32) -> %void { posix.EBUSY, posix.EINTR => continue, posix.EMFILE => error.ProcessFdQuotaExceeded, posix.EINVAL => unreachable, - else => error.Unexpected, + else => unexpectedErrorPosix(err), }; } return; @@ -404,7 +408,7 @@ fn posixExecveErrnoToErr(err: usize) -> error { posix.ENOENT => error.FileNotFound, posix.ENOTDIR => error.NotDir, posix.ETXTBSY => error.FileBusy, - else => error.Unexpected, + else => unexpectedErrorPosix(err), }; } @@ -491,7 +495,7 @@ pub fn getEnvVarOwned(allocator: &mem.Allocator, key: []const u8) -> %[]u8 { const err = windows.GetLastError(); return switch (err) { windows.ERROR.ENVVAR_NOT_FOUND => error.EnvironmentVariableNotFound, - else => error.Unexpected, + else => unexpectedErrorWindows(err), }; } @@ -519,7 +523,10 @@ pub fn getCwd(allocator: &Allocator) -> %[]u8 { const result = windows.GetCurrentDirectoryA(windows.WORD(buf.len), buf.ptr); if (result == 0) { - return error.Unexpected; + const err = windows.GetLastError(); + return switch (err) { + else => unexpectedErrorWindows(err), + }; } if (result > buf.len) { @@ -539,7 +546,7 @@ pub fn getCwd(allocator: &Allocator) -> %[]u8 { buf = %return allocator.realloc(u8, buf, buf.len * 2); continue; } else if (err > 0) { - return error.Unexpected; + return unexpectedErrorPosix(err); } return allocator.shrink(u8, buf, cstr.len(buf.ptr)); @@ -570,7 +577,7 @@ pub fn symLinkWindows(allocator: &Allocator, existing_path: []const u8, new_path if (windows.CreateSymbolicLinkA(existing_with_null.ptr, new_with_null.ptr, 0) == 0) { const err = windows.GetLastError(); return switch (err) { - else => error.Unexpected, + else => unexpectedErrorWindows(err), }; } } @@ -602,7 +609,7 @@ pub fn symLinkPosix(allocator: &Allocator, existing_path: []const u8, new_path: posix.ENOMEM => error.SystemResources, posix.ENOSPC => error.NoSpaceLeft, posix.EROFS => error.ReadOnlyFileSystem, - else => error.Unexpected, + else => unexpectedErrorPosix(err), }; } } @@ -663,7 +670,7 @@ pub fn deleteFileWindows(allocator: &Allocator, file_path: []const u8) -> %void windows.ERROR.FILE_NOT_FOUND => error.FileNotFound, windows.ERROR.ACCESS_DENIED => error.AccessDenied, windows.ERROR.FILENAME_EXCED_RANGE, windows.ERROR.INVALID_PARAMETER => error.NameTooLong, - else => error.Unexpected, + else => unexpectedErrorWindows(err), } } } @@ -689,7 +696,7 @@ pub fn deleteFilePosix(allocator: &Allocator, file_path: []const u8) -> %void { posix.ENOTDIR => error.NotDir, posix.ENOMEM => error.SystemResources, posix.EROFS => error.ReadOnlyFileSystem, - else => error.Unexpected, + else => unexpectedErrorPosix(err), }; } } @@ -743,7 +750,7 @@ pub fn rename(allocator: &Allocator, old_path: []const u8, new_path: []const u8) if (windows.MoveFileExA(old_buf.ptr, new_buf.ptr, flags) == 0) { const err = windows.GetLastError(); return switch (err) { - else => return error.Unexpected, + else => unexpectedErrorWindows(err), }; } } else { @@ -765,7 +772,7 @@ pub fn rename(allocator: &Allocator, old_path: []const u8, new_path: []const u8) posix.EEXIST, posix.ENOTEMPTY => error.PathAlreadyExists, posix.EROFS => error.ReadOnlyFileSystem, posix.EXDEV => error.RenameAcrossMountPoints, - else => error.Unexpected, + else => unexpectedErrorPosix(err), }; } } @@ -788,7 +795,7 @@ pub fn makeDirWindows(allocator: &Allocator, dir_path: []const u8) -> %void { return switch (err) { windows.ERROR.ALREADY_EXISTS => error.PathAlreadyExists, windows.ERROR.PATH_NOT_FOUND => error.FileNotFound, - else => error.Unexpected, + else => unexpectedErrorWindows(err), }; } } @@ -812,7 +819,7 @@ pub fn makeDirPosix(allocator: &Allocator, dir_path: []const u8) -> %void { posix.ENOSPC => error.NoSpaceLeft, posix.ENOTDIR => error.NotDir, posix.EROFS => error.ReadOnlyFileSystem, - else => error.Unexpected, + else => unexpectedErrorPosix(err), }; } } @@ -877,7 +884,7 @@ pub fn deleteDir(allocator: &Allocator, dir_path: []const u8) -> %void { posix.ENOTDIR => error.NotDir, posix.EEXIST, posix.ENOTEMPTY => error.DirNotEmpty, posix.EROFS => error.ReadOnlyFileSystem, - else => error.Unexpected, + else => unexpectedErrorPosix(err), }; } } @@ -988,7 +995,7 @@ pub const Dir = struct { self.buf = %return self.allocator.realloc(u8, self.buf, self.buf.len * 2); continue; }, - else => return error.Unexpected, + else => return unexpectedErrorPosix(err), }; } if (result == 0) @@ -1045,7 +1052,7 @@ pub fn changeCurDir(allocator: &Allocator, dir_path: []const u8) -> %void { posix.ENOENT => error.FileNotFound, posix.ENOMEM => error.SystemResources, posix.ENOTDIR => error.NotDir, - else => error.Unexpected, + else => unexpectedErrorPosix(err), }; } } @@ -1073,7 +1080,7 @@ pub fn readLink(allocator: &Allocator, pathname: []const u8) -> %[]u8 { posix.ENOENT => error.FileNotFound, posix.ENOMEM => error.SystemResources, posix.ENOTDIR => error.NotDir, - else => error.Unexpected, + else => unexpectedErrorPosix(err), }; } if (ret_val == result_buf.len) { @@ -1132,7 +1139,6 @@ test "os.sleep" { error ResourceLimitReached; error InvalidUserId; error PermissionDenied; -error Unexpected; pub fn posix_setuid(uid: u32) -> %void { const err = posix.getErrno(posix.setuid(uid)); @@ -1141,7 +1147,7 @@ pub fn posix_setuid(uid: u32) -> %void { posix.EAGAIN => error.ResourceLimitReached, posix.EINVAL => error.InvalidUserId, posix.EPERM => error.PermissionDenied, - else => error.Unexpected, + else => unexpectedErrorPosix(err), }; } @@ -1152,7 +1158,7 @@ pub fn posix_setreuid(ruid: u32, euid: u32) -> %void { posix.EAGAIN => error.ResourceLimitReached, posix.EINVAL => error.InvalidUserId, posix.EPERM => error.PermissionDenied, - else => error.Unexpected, + else => unexpectedErrorPosix(err), }; } @@ -1163,7 +1169,7 @@ pub fn posix_setgid(gid: u32) -> %void { posix.EAGAIN => error.ResourceLimitReached, posix.EINVAL => error.InvalidUserId, posix.EPERM => error.PermissionDenied, - else => error.Unexpected, + else => unexpectedErrorPosix(err), }; } @@ -1174,7 +1180,7 @@ pub fn posix_setregid(rgid: u32, egid: u32) -> %void { posix.EAGAIN => error.ResourceLimitReached, posix.EINVAL => error.InvalidUserId, posix.EPERM => error.PermissionDenied, - else => error.Unexpected, + else => unexpectedErrorPosix(err), }; } @@ -1417,3 +1423,29 @@ test "std.os" { _ = @import("path.zig"); _ = @import("windows/index.zig"); } + + +error Unexpected; + +// TODO make this a build variable that you can set +const unexpected_error_tracing = false; + +/// Call this when you made a syscall or something that sets errno +/// and you get an unexpected error. +pub fn unexpectedErrorPosix(errno: c_int) -> error { + if (unexpected_error_tracing) { + io.stderr.printf("unexpected errno: {}\n", errno) %% return; + debug.printStackTrace() %% return; + } + return error.Unexpected; +} + +/// Call this when you made a windows DLL call or something that does SetLastError +/// and you get an unexpected error. +pub fn unexpectedErrorWindows(err: windows.DWORD) -> error { + if (unexpected_error_tracing) { + io.stderr.printf("unexpected GetLastError(): {}\n", err) %% return; + debug.printStackTrace() %% return; + } + return error.Unexpected; +} diff --git a/std/os/path.zig b/std/os/path.zig index 93b7bc017c..beaabc38d6 100644 --- a/std/os/path.zig +++ b/std/os/path.zig @@ -915,7 +915,6 @@ error NotDir; error NameTooLong; error SymLinkLoop; error InputOutput; -error Unexpected; /// Return the canonicalized absolute pathname. /// Expands all symbolic links and resolves references to `.`, `..`, and /// extra `/` characters in ::pathname. @@ -938,7 +937,7 @@ pub fn real(allocator: &Allocator, pathname: []const u8) -> %[]u8 { windows.ERROR.FILE_NOT_FOUND => error.FileNotFound, windows.ERROR.ACCESS_DENIED => error.AccessDenied, windows.ERROR.FILENAME_EXCED_RANGE => error.NameTooLong, - else => error.Unexpected, + else => os.unexpectedErrorWindows(err), }; } defer os.windowsClose(h_file); @@ -954,7 +953,7 @@ pub fn real(allocator: &Allocator, pathname: []const u8) -> %[]u8 { windows.ERROR.PATH_NOT_FOUND => error.FileNotFound, windows.ERROR.NOT_ENOUGH_MEMORY => error.OutOfMemory, windows.ERROR.INVALID_PARAMETER => unreachable, - else => error.Unexpected, + else => os.unexpectedErrorWindows(err), }; } @@ -1003,7 +1002,7 @@ pub fn real(allocator: &Allocator, pathname: []const u8) -> %[]u8 { posix.ENAMETOOLONG => error.NameTooLong, posix.ELOOP => error.SymLinkLoop, posix.EIO => error.InputOutput, - else => error.Unexpected, + else => os.unexpectedErrorPosix(err), }; } return allocator.shrink(u8, result_buf, cstr.len(result_buf.ptr)); diff --git a/std/os/windows/util.zig b/std/os/windows/util.zig index 84eceb81af..de2babe8d7 100644 --- a/std/os/windows/util.zig +++ b/std/os/windows/util.zig @@ -7,6 +7,7 @@ const BufMap = std.BufMap; error WaitAbandoned; error WaitTimeOut; +error Unexpected; pub fn windowsWaitSingle(handle: windows.HANDLE, milliseconds: windows.DWORD) -> %void { const result = windows.WaitForSingleObject(handle, milliseconds); @@ -14,8 +15,11 @@ pub fn windowsWaitSingle(handle: windows.HANDLE, milliseconds: windows.DWORD) -> windows.WAIT_ABANDONED => error.WaitAbandoned, windows.WAIT_OBJECT_0 => {}, windows.WAIT_TIMEOUT => error.WaitTimeOut, - windows.WAIT_FAILED => switch (windows.GetLastError()) { - else => error.Unexpected, + windows.WAIT_FAILED => { + const err = windows.GetLastError(); + switch (err) { + else => os.unexpectedErrorWindows(err), + } }, else => error.Unexpected, }; @@ -32,14 +36,15 @@ error BrokenPipe; pub fn windowsWrite(handle: windows.HANDLE, bytes: []const u8) -> %void { if (windows.WriteFile(handle, @ptrCast(&const c_void, bytes.ptr), u32(bytes.len), null, null) == 0) { - return switch (windows.GetLastError()) { + const err = windows.GetLastError(); + return switch (err) { windows.ERROR.INVALID_USER_BUFFER => error.SystemResources, windows.ERROR.NOT_ENOUGH_MEMORY => error.SystemResources, windows.ERROR.OPERATION_ABORTED => error.OperationAborted, windows.ERROR.NOT_ENOUGH_QUOTA => error.SystemResources, windows.ERROR.IO_PENDING => error.IoPending, windows.ERROR.BROKEN_PIPE => error.BrokenPipe, - else => error.Unexpected, + else => os.unexpectedErrorWindows(err), }; } } @@ -106,7 +111,7 @@ pub fn windowsOpen(file_path: []const u8, desired_access: windows.DWORD, share_m windows.ERROR.FILE_NOT_FOUND => error.FileNotFound, windows.ERROR.ACCESS_DENIED => error.AccessDenied, windows.ERROR.PIPE_BUSY => error.PipeBusy, - else => error.Unexpected, + else => os.unexpectedErrorWindows(err), }; } |
