authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-10-15 16:45:43-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-10-15 16:45:43-04:00
logfcef7c4bb2f8705774b9d53c8f81a8e74cbcb630
tree0cc9202dac3d1715d1cd4f02ae899d7a579422a1
parentbb169a7b36a658ed463787655df54e3f59133d98

fix std.io.InStream for windows

now we handle PIPE_BROKEN as an EOF also set up framework for debugging unexpected posix/windows errors

6 files changed, 95 insertions(+), 58 deletions(-)

std/debug.zig+1
......@@ -11,6 +11,7 @@ error MissingDebugInfo;
1111error InvalidDebugInfo;
1212error UnsupportedDebugInfo;
1313
14
1415pub fn assert(ok: bool) {
1516 if (!ok) {
1617 // In ReleaseFast test mode, we still want assert(false) to crash, so
std/io.zig+17-16
......@@ -45,17 +45,12 @@ pub var stderr = OutStream {
4545/// bug in the program that called the function.
4646error Invalid;
4747
48/// When an Unexpected error occurs, code that emitted the error likely needs
49/// a patch to recognize the unexpected case so that it can handle it and emit
50/// a more specific error.
51error Unexpected;
52
5348error DiskQuota;
5449error FileTooBig;
5550error Io;
5651error NoSpaceLeft;
5752error BadPerm;
58error PipeFail;
53error BrokenPipe;
5954error BadFd;
6055error IsDir;
6156error NotDir;
......@@ -207,7 +202,10 @@ pub const OutStream = struct {
207202 if (self.handle) |handle| return handle;
208203 if (system.GetStdHandle(self.handle_id)) |handle| {
209204 if (handle == system.INVALID_HANDLE_VALUE) {
210 return error.Unexpected;
205 const err = system.GetLastError();
206 return switch (err) {
207 else => os.unexpectedErrorWindows(err),
208 };
211209 }
212210 self.handle = handle;
213211 return handle;
......@@ -292,7 +290,7 @@ pub const InStream = struct {
292290 system.EFAULT => unreachable,
293291 system.EBADF => return error.BadFd,
294292 system.EIO => return error.Io,
295 else => return error.Unexpected,
293 else => return os.unexpectedErrorPosix(read_err),
296294 }
297295 }
298296 if (amt_read == 0) return index;
......@@ -309,12 +307,12 @@ pub const InStream = struct {
309307 const err = system.GetLastError();
310308 return switch (err) {
311309 system.ERROR.OPERATION_ABORTED => continue,
312 system.ERROR.BROKEN_PIPE => error.PipeFail,
313 else => error.Unexpected,
310 system.ERROR.BROKEN_PIPE => return index,
311 else => os.unexpectedErrorWindows(err),
314312 };
315313 }
314 if (amt_read == 0) return index;
316315 index += amt_read;
317 if (amt_read < want_read_count) return index;
318316 }
319317 return index;
320318 } else {
......@@ -374,7 +372,7 @@ pub const InStream = struct {
374372 system.EOVERFLOW => error.Unseekable,
375373 system.ESPIPE => error.Unseekable,
376374 system.ENXIO => error.Unseekable,
377 else => error.Unexpected,
375 else => os.unexpectedErrorPosix(err),
378376 };
379377 }
380378 },
......@@ -394,7 +392,7 @@ pub const InStream = struct {
394392 system.EOVERFLOW => error.Unseekable,
395393 system.ESPIPE => error.Unseekable,
396394 system.ENXIO => error.Unseekable,
397 else => error.Unexpected,
395 else => os.unexpectedErrorPosix(err),
398396 };
399397 }
400398 },
......@@ -414,7 +412,7 @@ pub const InStream = struct {
414412 system.EOVERFLOW => error.Unseekable,
415413 system.ESPIPE => error.Unseekable,
416414 system.ENXIO => error.Unseekable,
417 else => error.Unexpected,
415 else => os.unexpectedErrorPosix(err),
418416 };
419417 }
420418 return result;
......@@ -430,7 +428,7 @@ pub const InStream = struct {
430428 return switch (err) {
431429 system.EBADF => error.BadFd,
432430 system.ENOMEM => error.OutOfMemory,
433 else => error.Unexpected,
431 else => os.unexpectedErrorPosix(err),
434432 }
435433 }
436434
......@@ -485,7 +483,10 @@ pub const InStream = struct {
485483 if (self.handle) |handle| return handle;
486484 if (system.GetStdHandle(self.handle_id)) |handle| {
487485 if (handle == system.INVALID_HANDLE_VALUE) {
488 return error.Unexpected;
486 const err = system.GetLastError();
487 return switch (err) {
488 else => os.unexpectedErrorWindows(err),
489 };
489490 }
490491 self.handle = handle;
491492 return handle;
std/net.zig-1
......@@ -3,7 +3,6 @@ const assert = @import("debug.zig").assert;
33const endian = @import("endian.zig");
44
55error SigInterrupt;
6error Unexpected;
76error Io;
87error TimedOut;
98error ConnectionReset;
std/os/index.zig+64-32
......@@ -51,7 +51,6 @@ const ArrayList = @import("../array_list.zig").ArrayList;
5151const Buffer = @import("../buffer.zig").Buffer;
5252const math = @import("../index.zig").math;
5353
54error Unexpected;
5554error SystemResources;
5655error AccessDenied;
5756error InvalidExe;
......@@ -81,7 +80,7 @@ pub fn getRandomBytes(buf: []u8) -> %void {
8180 posix.EINVAL => unreachable,
8281 posix.EFAULT => unreachable,
8382 posix.EINTR => continue,
84 else => error.Unexpected,
83 else => unexpectedErrorPosix(err),
8584 }
8685 }
8786 return;
......@@ -96,12 +95,18 @@ pub fn getRandomBytes(buf: []u8) -> %void {
9695 Os.windows => {
9796 var hCryptProv: windows.HCRYPTPROV = undefined;
9897 if (windows.CryptAcquireContextA(&hCryptProv, null, null, windows.PROV_RSA_FULL, 0) == 0) {
99 return error.Unexpected;
98 const err = windows.GetLastError();
99 return switch (err) {
100 else => unexpectedErrorWindows(err),
101 };
100102 }
101103 defer _ = windows.CryptReleaseContext(hCryptProv, 0);
102104
103105 if (windows.CryptGenRandom(hCryptProv, windows.DWORD(buf.len), buf.ptr) == 0) {
104 return error.Unexpected;
106 const err = windows.GetLastError();
107 return switch (err) {
108 else => unexpectedErrorWindows(err),
109 };
105110 }
106111 },
107112 else => @compileError("Unsupported OS"),
......@@ -187,8 +192,8 @@ pub fn posixRead(fd: i32, buf: []u8) -> %void {
187192 posix.EIO => error.InputOutput,
188193 posix.EISDIR => error.IsDir,
189194 posix.ENOBUFS, posix.ENOMEM => error.SystemResources,
190 else => return error.Unexpected,
191 }
195 else => unexpectedErrorPosix(err),
196 };
192197 }
193198 index += amt_written;
194199 }
......@@ -202,7 +207,6 @@ error FileTooBig;
202207error InputOutput;
203208error NoSpaceLeft;
204209error BrokenPipe;
205error Unexpected;
206210
207211/// Calls POSIX write, and keeps trying if it gets interrupted.
208212pub fn posixWrite(fd: i32, bytes: []const u8) -> %void {
......@@ -222,8 +226,8 @@ pub fn posixWrite(fd: i32, bytes: []const u8) -> %void {
222226 posix.ENOSPC => error.NoSpaceLeft,
223227 posix.EPERM => error.AccessDenied,
224228 posix.EPIPE => error.BrokenPipe,
225 else => error.Unexpected,
226 }
229 else => unexpectedErrorPosix(write_err),
230 };
227231 }
228232 return;
229233 }
......@@ -277,7 +281,7 @@ pub fn posixOpen(file_path: []const u8, flags: u32, perm: usize, allocator: ?&Al
277281 posix.ENOTDIR => error.NotDir,
278282 posix.EPERM => error.AccessDenied,
279283 posix.EEXIST => error.PathAlreadyExists,
280 else => error.Unexpected,
284 else => unexpectedErrorPosix(err),
281285 }
282286 }
283287 return i32(result);
......@@ -292,7 +296,7 @@ pub fn posixDup2(old_fd: i32, new_fd: i32) -> %void {
292296 posix.EBUSY, posix.EINTR => continue,
293297 posix.EMFILE => error.ProcessFdQuotaExceeded,
294298 posix.EINVAL => unreachable,
295 else => error.Unexpected,
299 else => unexpectedErrorPosix(err),
296300 };
297301 }
298302 return;
......@@ -404,7 +408,7 @@ fn posixExecveErrnoToErr(err: usize) -> error {
404408 posix.ENOENT => error.FileNotFound,
405409 posix.ENOTDIR => error.NotDir,
406410 posix.ETXTBSY => error.FileBusy,
407 else => error.Unexpected,
411 else => unexpectedErrorPosix(err),
408412 };
409413}
410414
......@@ -491,7 +495,7 @@ pub fn getEnvVarOwned(allocator: &mem.Allocator, key: []const u8) -> %[]u8 {
491495 const err = windows.GetLastError();
492496 return switch (err) {
493497 windows.ERROR.ENVVAR_NOT_FOUND => error.EnvironmentVariableNotFound,
494 else => error.Unexpected,
498 else => unexpectedErrorWindows(err),
495499 };
496500 }
497501
......@@ -519,7 +523,10 @@ pub fn getCwd(allocator: &Allocator) -> %[]u8 {
519523 const result = windows.GetCurrentDirectoryA(windows.WORD(buf.len), buf.ptr);
520524
521525 if (result == 0) {
522 return error.Unexpected;
526 const err = windows.GetLastError();
527 return switch (err) {
528 else => unexpectedErrorWindows(err),
529 };
523530 }
524531
525532 if (result > buf.len) {
......@@ -539,7 +546,7 @@ pub fn getCwd(allocator: &Allocator) -> %[]u8 {
539546 buf = %return allocator.realloc(u8, buf, buf.len * 2);
540547 continue;
541548 } else if (err > 0) {
542 return error.Unexpected;
549 return unexpectedErrorPosix(err);
543550 }
544551
545552 return allocator.shrink(u8, buf, cstr.len(buf.ptr));
......@@ -570,7 +577,7 @@ pub fn symLinkWindows(allocator: &Allocator, existing_path: []const u8, new_path
570577 if (windows.CreateSymbolicLinkA(existing_with_null.ptr, new_with_null.ptr, 0) == 0) {
571578 const err = windows.GetLastError();
572579 return switch (err) {
573 else => error.Unexpected,
580 else => unexpectedErrorWindows(err),
574581 };
575582 }
576583}
......@@ -602,7 +609,7 @@ pub fn symLinkPosix(allocator: &Allocator, existing_path: []const u8, new_path:
602609 posix.ENOMEM => error.SystemResources,
603610 posix.ENOSPC => error.NoSpaceLeft,
604611 posix.EROFS => error.ReadOnlyFileSystem,
605 else => error.Unexpected,
612 else => unexpectedErrorPosix(err),
606613 };
607614 }
608615}
......@@ -663,7 +670,7 @@ pub fn deleteFileWindows(allocator: &Allocator, file_path: []const u8) -> %void
663670 windows.ERROR.FILE_NOT_FOUND => error.FileNotFound,
664671 windows.ERROR.ACCESS_DENIED => error.AccessDenied,
665672 windows.ERROR.FILENAME_EXCED_RANGE, windows.ERROR.INVALID_PARAMETER => error.NameTooLong,
666 else => error.Unexpected,
673 else => unexpectedErrorWindows(err),
667674 }
668675 }
669676}
......@@ -689,7 +696,7 @@ pub fn deleteFilePosix(allocator: &Allocator, file_path: []const u8) -> %void {
689696 posix.ENOTDIR => error.NotDir,
690697 posix.ENOMEM => error.SystemResources,
691698 posix.EROFS => error.ReadOnlyFileSystem,
692 else => error.Unexpected,
699 else => unexpectedErrorPosix(err),
693700 };
694701 }
695702}
......@@ -743,7 +750,7 @@ pub fn rename(allocator: &Allocator, old_path: []const u8, new_path: []const u8)
743750 if (windows.MoveFileExA(old_buf.ptr, new_buf.ptr, flags) == 0) {
744751 const err = windows.GetLastError();
745752 return switch (err) {
746 else => return error.Unexpected,
753 else => unexpectedErrorWindows(err),
747754 };
748755 }
749756 } else {
......@@ -765,7 +772,7 @@ pub fn rename(allocator: &Allocator, old_path: []const u8, new_path: []const u8)
765772 posix.EEXIST, posix.ENOTEMPTY => error.PathAlreadyExists,
766773 posix.EROFS => error.ReadOnlyFileSystem,
767774 posix.EXDEV => error.RenameAcrossMountPoints,
768 else => error.Unexpected,
775 else => unexpectedErrorPosix(err),
769776 };
770777 }
771778 }
......@@ -788,7 +795,7 @@ pub fn makeDirWindows(allocator: &Allocator, dir_path: []const u8) -> %void {
788795 return switch (err) {
789796 windows.ERROR.ALREADY_EXISTS => error.PathAlreadyExists,
790797 windows.ERROR.PATH_NOT_FOUND => error.FileNotFound,
791 else => error.Unexpected,
798 else => unexpectedErrorWindows(err),
792799 };
793800 }
794801}
......@@ -812,7 +819,7 @@ pub fn makeDirPosix(allocator: &Allocator, dir_path: []const u8) -> %void {
812819 posix.ENOSPC => error.NoSpaceLeft,
813820 posix.ENOTDIR => error.NotDir,
814821 posix.EROFS => error.ReadOnlyFileSystem,
815 else => error.Unexpected,
822 else => unexpectedErrorPosix(err),
816823 };
817824 }
818825}
......@@ -877,7 +884,7 @@ pub fn deleteDir(allocator: &Allocator, dir_path: []const u8) -> %void {
877884 posix.ENOTDIR => error.NotDir,
878885 posix.EEXIST, posix.ENOTEMPTY => error.DirNotEmpty,
879886 posix.EROFS => error.ReadOnlyFileSystem,
880 else => error.Unexpected,
887 else => unexpectedErrorPosix(err),
881888 };
882889 }
883890}
......@@ -988,7 +995,7 @@ pub const Dir = struct {
988995 self.buf = %return self.allocator.realloc(u8, self.buf, self.buf.len * 2);
989996 continue;
990997 },
991 else => return error.Unexpected,
998 else => return unexpectedErrorPosix(err),
992999 };
9931000 }
9941001 if (result == 0)
......@@ -1045,7 +1052,7 @@ pub fn changeCurDir(allocator: &Allocator, dir_path: []const u8) -> %void {
10451052 posix.ENOENT => error.FileNotFound,
10461053 posix.ENOMEM => error.SystemResources,
10471054 posix.ENOTDIR => error.NotDir,
1048 else => error.Unexpected,
1055 else => unexpectedErrorPosix(err),
10491056 };
10501057 }
10511058}
......@@ -1073,7 +1080,7 @@ pub fn readLink(allocator: &Allocator, pathname: []const u8) -> %[]u8 {
10731080 posix.ENOENT => error.FileNotFound,
10741081 posix.ENOMEM => error.SystemResources,
10751082 posix.ENOTDIR => error.NotDir,
1076 else => error.Unexpected,
1083 else => unexpectedErrorPosix(err),
10771084 };
10781085 }
10791086 if (ret_val == result_buf.len) {
......@@ -1132,7 +1139,6 @@ test "os.sleep" {
11321139error ResourceLimitReached;
11331140error InvalidUserId;
11341141error PermissionDenied;
1135error Unexpected;
11361142
11371143pub fn posix_setuid(uid: u32) -> %void {
11381144 const err = posix.getErrno(posix.setuid(uid));
......@@ -1141,7 +1147,7 @@ pub fn posix_setuid(uid: u32) -> %void {
11411147 posix.EAGAIN => error.ResourceLimitReached,
11421148 posix.EINVAL => error.InvalidUserId,
11431149 posix.EPERM => error.PermissionDenied,
1144 else => error.Unexpected,
1150 else => unexpectedErrorPosix(err),
11451151 };
11461152}
11471153
......@@ -1152,7 +1158,7 @@ pub fn posix_setreuid(ruid: u32, euid: u32) -> %void {
11521158 posix.EAGAIN => error.ResourceLimitReached,
11531159 posix.EINVAL => error.InvalidUserId,
11541160 posix.EPERM => error.PermissionDenied,
1155 else => error.Unexpected,
1161 else => unexpectedErrorPosix(err),
11561162 };
11571163}
11581164
......@@ -1163,7 +1169,7 @@ pub fn posix_setgid(gid: u32) -> %void {
11631169 posix.EAGAIN => error.ResourceLimitReached,
11641170 posix.EINVAL => error.InvalidUserId,
11651171 posix.EPERM => error.PermissionDenied,
1166 else => error.Unexpected,
1172 else => unexpectedErrorPosix(err),
11671173 };
11681174}
11691175
......@@ -1174,7 +1180,7 @@ pub fn posix_setregid(rgid: u32, egid: u32) -> %void {
11741180 posix.EAGAIN => error.ResourceLimitReached,
11751181 posix.EINVAL => error.InvalidUserId,
11761182 posix.EPERM => error.PermissionDenied,
1177 else => error.Unexpected,
1183 else => unexpectedErrorPosix(err),
11781184 };
11791185}
11801186
......@@ -1417,3 +1423,29 @@ test "std.os" {
14171423 _ = @import("path.zig");
14181424 _ = @import("windows/index.zig");
14191425}
1426
1427
1428error Unexpected;
1429
1430// TODO make this a build variable that you can set
1431const unexpected_error_tracing = false;
1432
1433/// Call this when you made a syscall or something that sets errno
1434/// and you get an unexpected error.
1435pub fn unexpectedErrorPosix(errno: c_int) -> error {
1436 if (unexpected_error_tracing) {
1437 io.stderr.printf("unexpected errno: {}\n", errno) %% return;
1438 debug.printStackTrace() %% return;
1439 }
1440 return error.Unexpected;
1441}
1442
1443/// Call this when you made a windows DLL call or something that does SetLastError
1444/// and you get an unexpected error.
1445pub fn unexpectedErrorWindows(err: windows.DWORD) -> error {
1446 if (unexpected_error_tracing) {
1447 io.stderr.printf("unexpected GetLastError(): {}\n", err) %% return;
1448 debug.printStackTrace() %% return;
1449 }
1450 return error.Unexpected;
1451}
std/os/path.zig+3-4
......@@ -915,7 +915,6 @@ error NotDir;
915915error NameTooLong;
916916error SymLinkLoop;
917917error InputOutput;
918error Unexpected;
919918/// Return the canonicalized absolute pathname.
920919/// Expands all symbolic links and resolves references to `.`, `..`, and
921920/// extra `/` characters in ::pathname.
......@@ -938,7 +937,7 @@ pub fn real(allocator: &Allocator, pathname: []const u8) -> %[]u8 {
938937 windows.ERROR.FILE_NOT_FOUND => error.FileNotFound,
939938 windows.ERROR.ACCESS_DENIED => error.AccessDenied,
940939 windows.ERROR.FILENAME_EXCED_RANGE => error.NameTooLong,
941 else => error.Unexpected,
940 else => os.unexpectedErrorWindows(err),
942941 };
943942 }
944943 defer os.windowsClose(h_file);
......@@ -954,7 +953,7 @@ pub fn real(allocator: &Allocator, pathname: []const u8) -> %[]u8 {
954953 windows.ERROR.PATH_NOT_FOUND => error.FileNotFound,
955954 windows.ERROR.NOT_ENOUGH_MEMORY => error.OutOfMemory,
956955 windows.ERROR.INVALID_PARAMETER => unreachable,
957 else => error.Unexpected,
956 else => os.unexpectedErrorWindows(err),
958957 };
959958 }
960959
......@@ -1003,7 +1002,7 @@ pub fn real(allocator: &Allocator, pathname: []const u8) -> %[]u8 {
10031002 posix.ENAMETOOLONG => error.NameTooLong,
10041003 posix.ELOOP => error.SymLinkLoop,
10051004 posix.EIO => error.InputOutput,
1006 else => error.Unexpected,
1005 else => os.unexpectedErrorPosix(err),
10071006 };
10081007 }
10091008 return allocator.shrink(u8, result_buf, cstr.len(result_buf.ptr));
std/os/windows/util.zig+10-5
......@@ -7,6 +7,7 @@ const BufMap = std.BufMap;
77
88error WaitAbandoned;
99error WaitTimeOut;
10error Unexpected;
1011
1112pub fn windowsWaitSingle(handle: windows.HANDLE, milliseconds: windows.DWORD) -> %void {
1213 const result = windows.WaitForSingleObject(handle, milliseconds);
......@@ -14,8 +15,11 @@ pub fn windowsWaitSingle(handle: windows.HANDLE, milliseconds: windows.DWORD) ->
1415 windows.WAIT_ABANDONED => error.WaitAbandoned,
1516 windows.WAIT_OBJECT_0 => {},
1617 windows.WAIT_TIMEOUT => error.WaitTimeOut,
17 windows.WAIT_FAILED => switch (windows.GetLastError()) {
18 else => error.Unexpected,
18 windows.WAIT_FAILED => {
19 const err = windows.GetLastError();
20 switch (err) {
21 else => os.unexpectedErrorWindows(err),
22 }
1923 },
2024 else => error.Unexpected,
2125 };
......@@ -32,14 +36,15 @@ error BrokenPipe;
3236
3337pub fn windowsWrite(handle: windows.HANDLE, bytes: []const u8) -> %void {
3438 if (windows.WriteFile(handle, @ptrCast(&const c_void, bytes.ptr), u32(bytes.len), null, null) == 0) {
35 return switch (windows.GetLastError()) {
39 const err = windows.GetLastError();
40 return switch (err) {
3641 windows.ERROR.INVALID_USER_BUFFER => error.SystemResources,
3742 windows.ERROR.NOT_ENOUGH_MEMORY => error.SystemResources,
3843 windows.ERROR.OPERATION_ABORTED => error.OperationAborted,
3944 windows.ERROR.NOT_ENOUGH_QUOTA => error.SystemResources,
4045 windows.ERROR.IO_PENDING => error.IoPending,
4146 windows.ERROR.BROKEN_PIPE => error.BrokenPipe,
42 else => error.Unexpected,
47 else => os.unexpectedErrorWindows(err),
4348 };
4449 }
4550}
......@@ -106,7 +111,7 @@ pub fn windowsOpen(file_path: []const u8, desired_access: windows.DWORD, share_m
106111 windows.ERROR.FILE_NOT_FOUND => error.FileNotFound,
107112 windows.ERROR.ACCESS_DENIED => error.AccessDenied,
108113 windows.ERROR.PIPE_BUSY => error.PipeBusy,
109 else => error.Unexpected,
114 else => os.unexpectedErrorWindows(err),
110115 };
111116 }
112117