| author | |
| committer | |
| log | 7998e2b0f41bff86d8fbbb8112dd6c629d47e849 |
| tree | 9f7bca5991f9fcdb291da10e2c830a749769dfad |
| parent | 5656f5090d8646e076db50da03cfc6ae686eb76b |
| parent | 8ebcca6734e07aea29098ca4c63c0216b3099d0e |
8 files changed, 78 insertions(+), 27 deletions(-)
ci/azure/linux_script+1-1| ... | @@ -14,7 +14,7 @@ sudo apt-get remove -y llvm-* | ... | @@ -14,7 +14,7 @@ sudo apt-get remove -y llvm-* |
| 14 | sudo rm -rf /usr/local/* | 14 | sudo rm -rf /usr/local/* |
| 15 | sudo apt-get install -y libxml2-dev libclang-10-dev llvm-10 llvm-10-dev liblld-10-dev cmake s3cmd gcc-7 g++-7 | 15 | sudo apt-get install -y libxml2-dev libclang-10-dev llvm-10 llvm-10-dev liblld-10-dev cmake s3cmd gcc-7 g++-7 |
| 16 | 16 | ||
| 17 | QEMUBASE="qemu-linux-x86_64-5.0.0" | 17 | QEMUBASE="qemu-linux-x86_64-5.0.0-z2" |
| 18 | wget https://ziglang.org/deps/$QEMUBASE.tar.xz | 18 | wget https://ziglang.org/deps/$QEMUBASE.tar.xz |
| 19 | tar xf $QEMUBASE.tar.xz | 19 | tar xf $QEMUBASE.tar.xz |
| 20 | PATH=$PWD/$QEMUBASE/bin:$PATH | 20 | PATH=$PWD/$QEMUBASE/bin:$PATH |
lib/std/c/netbsd.zig+1| ... | @@ -9,6 +9,7 @@ pub const _errno = __errno; | ... | @@ -9,6 +9,7 @@ pub const _errno = __errno; |
| 9 | pub const dl_iterate_phdr_callback = extern fn (info: *dl_phdr_info, size: usize, data: ?*c_void) c_int; | 9 | pub const dl_iterate_phdr_callback = extern fn (info: *dl_phdr_info, size: usize, data: ?*c_void) c_int; |
| 10 | pub extern "c" fn dl_iterate_phdr(callback: dl_iterate_phdr_callback, data: ?*c_void) c_int; | 10 | pub extern "c" fn dl_iterate_phdr(callback: dl_iterate_phdr_callback, data: ?*c_void) c_int; |
| 11 | 11 | ||
| 12 | pub extern "c" fn arc4random_buf(buf: [*]u8, len: usize) void; | ||
| 12 | pub extern "c" fn __fstat50(fd: fd_t, buf: *Stat) c_int; | 13 | pub extern "c" fn __fstat50(fd: fd_t, buf: *Stat) c_int; |
| 13 | pub extern "c" fn __stat50(path: [*:0]const u8, buf: *Stat) c_int; | 14 | pub extern "c" fn __stat50(path: [*:0]const u8, buf: *Stat) c_int; |
| 14 | pub extern "c" fn __clock_gettime50(clk_id: c_int, tp: *timespec) c_int; | 15 | pub extern "c" fn __clock_gettime50(clk_id: c_int, tp: *timespec) c_int; |
lib/std/event/loop.zig+40-18| ... | @@ -467,18 +467,43 @@ pub const Loop = struct { | ... | @@ -467,18 +467,43 @@ pub const Loop = struct { |
| 467 | } | 467 | } |
| 468 | 468 | ||
| 469 | pub fn waitUntilFdReadable(self: *Loop, fd: os.fd_t) void { | 469 | pub fn waitUntilFdReadable(self: *Loop, fd: os.fd_t) void { |
| 470 | return self.linuxWaitFd(fd, os.EPOLLET | os.EPOLLONESHOT | os.EPOLLIN); | 470 | switch (builtin.os.tag) { |
| 471 | .linux => { | ||
| 472 | self.linuxWaitFd(fd, os.EPOLLET | os.EPOLLONESHOT | os.EPOLLIN); | ||
| 473 | }, | ||
| 474 | .macosx, .freebsd, .netbsd, .dragonfly => { | ||
| 475 | self.bsdWaitKev(@intCast(usize, fd), os.EVFILT_READ, os.EV_ONESHOT); | ||
| 476 | }, | ||
| 477 | else => @compileError("Unsupported OS"), | ||
| 478 | } | ||
| 471 | } | 479 | } |
| 472 | 480 | ||
| 473 | pub fn waitUntilFdWritable(self: *Loop, fd: os.fd_t) void { | 481 | pub fn waitUntilFdWritable(self: *Loop, fd: os.fd_t) void { |
| 474 | return self.linuxWaitFd(fd, os.EPOLLET | os.EPOLLONESHOT | os.EPOLLOUT); | 482 | switch (builtin.os.tag) { |
| 483 | .linux => { | ||
| 484 | self.linuxWaitFd(fd, os.EPOLLET | os.EPOLLONESHOT | os.EPOLLOUT); | ||
| 485 | }, | ||
| 486 | .macosx, .freebsd, .netbsd, .dragonfly => { | ||
| 487 | self.bsdWaitKev(@intCast(usize, fd), os.EVFILT_WRITE, os.EV_ONESHOT); | ||
| 488 | }, | ||
| 489 | else => @compileError("Unsupported OS"), | ||
| 490 | } | ||
| 475 | } | 491 | } |
| 476 | 492 | ||
| 477 | pub fn waitUntilFdWritableOrReadable(self: *Loop, fd: os.fd_t) void { | 493 | pub fn waitUntilFdWritableOrReadable(self: *Loop, fd: os.fd_t) void { |
| 478 | return self.linuxWaitFd(fd, os.EPOLLET | os.EPOLLONESHOT | os.EPOLLOUT | os.EPOLLIN); | 494 | switch (builtin.os.tag) { |
| 495 | .linux => { | ||
| 496 | self.linuxWaitFd(@intCast(usize, fd), os.EPOLLET | os.EPOLLONESHOT | os.EPOLLOUT | os.EPOLLIN); | ||
| 497 | }, | ||
| 498 | .macosx, .freebsd, .netbsd, .dragonfly => { | ||
| 499 | self.bsdWaitKev(@intCast(usize, fd), os.EVFILT_READ, os.EV_ONESHOT); | ||
| 500 | self.bsdWaitKev(@intCast(usize, fd), os.EVFILT_WRITE, os.EV_ONESHOT); | ||
| 501 | }, | ||
| 502 | else => @compileError("Unsupported OS"), | ||
| 503 | } | ||
| 479 | } | 504 | } |
| 480 | 505 | ||
| 481 | pub async fn bsdWaitKev(self: *Loop, ident: usize, filter: i16, fflags: u32) !os.Kevent { | 506 | pub async fn bsdWaitKev(self: *Loop, ident: usize, filter: i16, fflags: u32) void { |
| 482 | var resume_node = ResumeNode.Basic{ | 507 | var resume_node = ResumeNode.Basic{ |
| 483 | .base = ResumeNode{ | 508 | .base = ResumeNode{ |
| 484 | .id = ResumeNode.Id.Basic, | 509 | .id = ResumeNode.Id.Basic, |
| ... | @@ -489,40 +514,37 @@ pub const Loop = struct { | ... | @@ -489,40 +514,37 @@ pub const Loop = struct { |
| 489 | }; | 514 | }; |
| 490 | defer self.bsdRemoveKev(ident, filter); | 515 | defer self.bsdRemoveKev(ident, filter); |
| 491 | suspend { | 516 | suspend { |
| 492 | try self.bsdAddKev(&resume_node, ident, filter, fflags); | 517 | self.bsdAddKev(&resume_node, ident, filter, fflags) catch unreachable; |
| 493 | } | 518 | } |
| 494 | return resume_node.kev; | ||
| 495 | } | 519 | } |
| 496 | 520 | ||
| 497 | /// resume_node must live longer than the anyframe that it holds a reference to. | 521 | /// resume_node must live longer than the anyframe that it holds a reference to. |
| 498 | pub fn bsdAddKev(self: *Loop, resume_node: *ResumeNode.Basic, ident: usize, filter: i16, fflags: u32) !void { | 522 | pub fn bsdAddKev(self: *Loop, resume_node: *ResumeNode.Basic, ident: usize, filter: i16, fflags: u32) !void { |
| 499 | self.beginOneEvent(); | 523 | self.beginOneEvent(); |
| 500 | errdefer self.finishOneEvent(); | 524 | errdefer self.finishOneEvent(); |
| 501 | var kev = os.Kevent{ | 525 | var kev = [1]os.Kevent{os.Kevent{ |
| 502 | .ident = ident, | 526 | .ident = ident, |
| 503 | .filter = filter, | 527 | .filter = filter, |
| 504 | .flags = os.EV_ADD | os.EV_ENABLE | os.EV_CLEAR, | 528 | .flags = os.EV_ADD | os.EV_ENABLE | os.EV_CLEAR, |
| 505 | .fflags = fflags, | 529 | .fflags = fflags, |
| 506 | .data = 0, | 530 | .data = 0, |
| 507 | .udata = @ptrToInt(&resume_node.base), | 531 | .udata = @ptrToInt(&resume_node.base), |
| 508 | }; | 532 | }}; |
| 509 | const kevent_array = (*const [1]os.Kevent)(&kev); | 533 | const empty_kevs = &[0]os.Kevent{}; |
| 510 | const empty_kevs = ([*]os.Kevent)(undefined)[0..0]; | 534 | _ = try os.kevent(self.os_data.kqfd, &kev, empty_kevs, null); |
| 511 | _ = try os.kevent(self.os_data.kqfd, kevent_array, empty_kevs, null); | ||
| 512 | } | 535 | } |
| 513 | 536 | ||
| 514 | pub fn bsdRemoveKev(self: *Loop, ident: usize, filter: i16) void { | 537 | pub fn bsdRemoveKev(self: *Loop, ident: usize, filter: i16) void { |
| 515 | var kev = os.Kevent{ | 538 | var kev = [1]os.Kevent{os.Kevent{ |
| 516 | .ident = ident, | 539 | .ident = ident, |
| 517 | .filter = filter, | 540 | .filter = filter, |
| 518 | .flags = os.EV_DELETE, | 541 | .flags = os.EV_DELETE, |
| 519 | .fflags = 0, | 542 | .fflags = 0, |
| 520 | .data = 0, | 543 | .data = 0, |
| 521 | .udata = 0, | 544 | .udata = 0, |
| 522 | }; | 545 | }}; |
| 523 | const kevent_array = (*const [1]os.Kevent)(&kev); | 546 | const empty_kevs = &[0]os.Kevent{}; |
| 524 | const empty_kevs = ([*]os.Kevent)(undefined)[0..0]; | 547 | _ = os.kevent(self.os_data.kqfd, &kev, empty_kevs, null) catch undefined; |
| 525 | _ = os.kevent(self.os_data.kqfd, kevent_array, empty_kevs, null) catch undefined; | ||
| 526 | self.finishOneEvent(); | 548 | self.finishOneEvent(); |
| 527 | } | 549 | } |
| 528 | 550 | ||
| ... | @@ -679,7 +701,7 @@ pub const Loop = struct { | ... | @@ -679,7 +701,7 @@ pub const Loop = struct { |
| 679 | } | 701 | } |
| 680 | 702 | ||
| 681 | /// Performs an async `os.open` using a separate thread. | 703 | /// Performs an async `os.open` using a separate thread. |
| 682 | pub fn openZ(self: *Loop, file_path: [*:0]const u8, flags: u32, mode: usize) os.OpenError!os.fd_t { | 704 | pub fn openZ(self: *Loop, file_path: [*:0]const u8, flags: u32, mode: os.mode_t) os.OpenError!os.fd_t { |
| 683 | var req_node = Request.Node{ | 705 | var req_node = Request.Node{ |
| 684 | .data = .{ | 706 | .data = .{ |
| 685 | .msg = .{ | 707 | .msg = .{ |
| ... | @@ -700,7 +722,7 @@ pub const Loop = struct { | ... | @@ -700,7 +722,7 @@ pub const Loop = struct { |
| 700 | } | 722 | } |
| 701 | 723 | ||
| 702 | /// Performs an async `os.opent` using a separate thread. | 724 | /// Performs an async `os.opent` using a separate thread. |
| 703 | pub fn openatZ(self: *Loop, fd: os.fd_t, file_path: [*:0]const u8, flags: u32, mode: usize) os.OpenError!os.fd_t { | 725 | pub fn openatZ(self: *Loop, fd: os.fd_t, file_path: [*:0]const u8, flags: u32, mode: os.mode_t) os.OpenError!os.fd_t { |
| 704 | var req_node = Request.Node{ | 726 | var req_node = Request.Node{ |
| 705 | .data = .{ | 727 | .data = .{ |
| 706 | .msg = .{ | 728 | .msg = .{ |
lib/std/fs.zig+3-3| ... | @@ -1449,7 +1449,7 @@ pub fn createFileAbsoluteW(absolute_path_w: [*:0]const u16, flags: File.CreateFl | ... | @@ -1449,7 +1449,7 @@ pub fn createFileAbsoluteW(absolute_path_w: [*:0]const u16, flags: File.CreateFl |
| 1449 | /// Asserts that the path is absolute. See `Dir.deleteFile` for a function that | 1449 | /// Asserts that the path is absolute. See `Dir.deleteFile` for a function that |
| 1450 | /// operates on both absolute and relative paths. | 1450 | /// operates on both absolute and relative paths. |
| 1451 | /// Asserts that the path parameter has no null bytes. | 1451 | /// Asserts that the path parameter has no null bytes. |
| 1452 | pub fn deleteFileAbsolute(absolute_path: []const u8) DeleteFileError!void { | 1452 | pub fn deleteFileAbsolute(absolute_path: []const u8) Dir.DeleteFileError!void { |
| 1453 | assert(path.isAbsolute(absolute_path)); | 1453 | assert(path.isAbsolute(absolute_path)); |
| 1454 | return cwd().deleteFile(absolute_path); | 1454 | return cwd().deleteFile(absolute_path); |
| 1455 | } | 1455 | } |
| ... | @@ -1457,13 +1457,13 @@ pub fn deleteFileAbsolute(absolute_path: []const u8) DeleteFileError!void { | ... | @@ -1457,13 +1457,13 @@ pub fn deleteFileAbsolute(absolute_path: []const u8) DeleteFileError!void { |
| 1457 | pub const deleteFileAbsoluteC = @compileError("deprecated: renamed to deleteFileAbsoluteZ"); | 1457 | pub const deleteFileAbsoluteC = @compileError("deprecated: renamed to deleteFileAbsoluteZ"); |
| 1458 | 1458 | ||
| 1459 | /// Same as `deleteFileAbsolute` except the parameter is null-terminated. | 1459 | /// Same as `deleteFileAbsolute` except the parameter is null-terminated. |
| 1460 | pub fn deleteFileAbsoluteZ(absolute_path_c: [*:0]const u8) DeleteFileError!void { | 1460 | pub fn deleteFileAbsoluteZ(absolute_path_c: [*:0]const u8) Dir.DeleteFileError!void { |
| 1461 | assert(path.isAbsoluteZ(absolute_path_c)); | 1461 | assert(path.isAbsoluteZ(absolute_path_c)); |
| 1462 | return cwd().deleteFileZ(absolute_path_c); | 1462 | return cwd().deleteFileZ(absolute_path_c); |
| 1463 | } | 1463 | } |
| 1464 | 1464 | ||
| 1465 | /// Same as `deleteFileAbsolute` except the parameter is WTF-16 encoded. | 1465 | /// Same as `deleteFileAbsolute` except the parameter is WTF-16 encoded. |
| 1466 | pub fn deleteFileAbsoluteW(absolute_path_w: [*:0]const u16) DeleteFileError!void { | 1466 | pub fn deleteFileAbsoluteW(absolute_path_w: [*:0]const u16) Dir.DeleteFileError!void { |
| 1467 | assert(path.isAbsoluteWindowsW(absolute_path_w)); | 1467 | assert(path.isAbsoluteWindowsW(absolute_path_w)); |
| 1468 | return cwd().deleteFileW(absolute_path_w); | 1468 | return cwd().deleteFileW(absolute_path_w); |
| 1469 | } | 1469 | } |
lib/std/fs/test.zig+16| ... | @@ -110,6 +110,22 @@ test "create file, lock and read from multiple process at once" { | ... | @@ -110,6 +110,22 @@ test "create file, lock and read from multiple process at once" { |
| 110 | }; | 110 | }; |
| 111 | } | 111 | } |
| 112 | 112 | ||
| 113 | test "open file with exclusive nonblocking lock twice (absolute paths)" { | ||
| 114 | const allocator = std.testing.allocator; | ||
| 115 | |||
| 116 | const file_paths: [1][]const u8 = .{"zig-test-absolute-paths.txt"}; | ||
| 117 | const filename = try fs.path.resolve(allocator, &file_paths); | ||
| 118 | defer allocator.free(filename); | ||
| 119 | |||
| 120 | const file1 = try fs.createFileAbsolute(filename, .{ .lock = .Exclusive, .lock_nonblocking = true }); | ||
| 121 | |||
| 122 | const file2 = fs.createFileAbsolute(filename, .{ .lock = .Exclusive, .lock_nonblocking = true }); | ||
| 123 | file1.close(); | ||
| 124 | std.testing.expectError(error.WouldBlock, file2); | ||
| 125 | |||
| 126 | try fs.deleteFileAbsolute(filename); | ||
| 127 | } | ||
| 128 | |||
| 113 | const FileLockTestContext = struct { | 129 | const FileLockTestContext = struct { |
| 114 | filename: []const u8, | 130 | filename: []const u8, |
| 115 | pid: if (builtin.os.tag == .windows) ?void else ?std.os.pid_t = null, | 131 | pid: if (builtin.os.tag == .windows) ?void else ?std.os.pid_t = null, |
lib/std/os.zig+6-2| ... | @@ -153,6 +153,10 @@ pub fn getrandom(buffer: []u8) GetRandomError!void { | ... | @@ -153,6 +153,10 @@ pub fn getrandom(buffer: []u8) GetRandomError!void { |
| 153 | } | 153 | } |
| 154 | return; | 154 | return; |
| 155 | } | 155 | } |
| 156 | if (builtin.os.tag == .netbsd) { | ||
| 157 | netbsd.arc4random_buf(buffer.ptr, buffer.len); | ||
| 158 | return; | ||
| 159 | } | ||
| 156 | if (builtin.os.tag == .wasi) { | 160 | if (builtin.os.tag == .wasi) { |
| 157 | switch (wasi.random_get(buffer.ptr, buffer.len)) { | 161 | switch (wasi.random_get(buffer.ptr, buffer.len)) { |
| 158 | 0 => return, | 162 | 0 => return, |
| ... | @@ -854,7 +858,7 @@ pub const OpenError = error{ | ... | @@ -854,7 +858,7 @@ pub const OpenError = error{ |
| 854 | 858 | ||
| 855 | /// Open and possibly create a file. Keeps trying if it gets interrupted. | 859 | /// Open and possibly create a file. Keeps trying if it gets interrupted. |
| 856 | /// See also `openC`. | 860 | /// See also `openC`. |
| 857 | pub fn open(file_path: []const u8, flags: u32, perm: usize) OpenError!fd_t { | 861 | pub fn open(file_path: []const u8, flags: u32, perm: mode_t) OpenError!fd_t { |
| 858 | if (std.Target.current.os.tag == .windows) { | 862 | if (std.Target.current.os.tag == .windows) { |
| 859 | const file_path_w = try windows.sliceToPrefixedFileW(file_path); | 863 | const file_path_w = try windows.sliceToPrefixedFileW(file_path); |
| 860 | return openW(file_path_w.span(), flags, perm); | 864 | return openW(file_path_w.span(), flags, perm); |
| ... | @@ -867,7 +871,7 @@ pub const openC = @compileError("deprecated: renamed to openZ"); | ... | @@ -867,7 +871,7 @@ pub const openC = @compileError("deprecated: renamed to openZ"); |
| 867 | 871 | ||
| 868 | /// Open and possibly create a file. Keeps trying if it gets interrupted. | 872 | /// Open and possibly create a file. Keeps trying if it gets interrupted. |
| 869 | /// See also `open`. | 873 | /// See also `open`. |
| 870 | pub fn openZ(file_path: [*:0]const u8, flags: u32, perm: usize) OpenError!fd_t { | 874 | pub fn openZ(file_path: [*:0]const u8, flags: u32, perm: mode_t) OpenError!fd_t { |
| 871 | if (std.Target.current.os.tag == .windows) { | 875 | if (std.Target.current.os.tag == .windows) { |
| 872 | const file_path_w = try windows.cStrToPrefixedFileW(file_path); | 876 | const file_path_w = try windows.cStrToPrefixedFileW(file_path); |
| 873 | return openW(file_path_w.span(), flags, perm); | 877 | return openW(file_path_w.span(), flags, perm); |
lib/std/os/linux.zig+3-3| ... | @@ -492,7 +492,7 @@ pub fn renameat2(oldfd: i32, oldpath: [*:0]const u8, newfd: i32, newpath: [*:0]c | ... | @@ -492,7 +492,7 @@ pub fn renameat2(oldfd: i32, oldpath: [*:0]const u8, newfd: i32, newpath: [*:0]c |
| 492 | ); | 492 | ); |
| 493 | } | 493 | } |
| 494 | 494 | ||
| 495 | pub fn open(path: [*:0]const u8, flags: u32, perm: usize) usize { | 495 | pub fn open(path: [*:0]const u8, flags: u32, perm: mode_t) usize { |
| 496 | if (@hasField(SYS, "open")) { | 496 | if (@hasField(SYS, "open")) { |
| 497 | return syscall3(.open, @ptrToInt(path), flags, perm); | 497 | return syscall3(.open, @ptrToInt(path), flags, perm); |
| 498 | } else { | 498 | } else { |
| ... | @@ -506,11 +506,11 @@ pub fn open(path: [*:0]const u8, flags: u32, perm: usize) usize { | ... | @@ -506,11 +506,11 @@ pub fn open(path: [*:0]const u8, flags: u32, perm: usize) usize { |
| 506 | } | 506 | } |
| 507 | } | 507 | } |
| 508 | 508 | ||
| 509 | pub fn create(path: [*:0]const u8, perm: usize) usize { | 509 | pub fn create(path: [*:0]const u8, perm: mode_t) usize { |
| 510 | return syscall2(.creat, @ptrToInt(path), perm); | 510 | return syscall2(.creat, @ptrToInt(path), perm); |
| 511 | } | 511 | } |
| 512 | 512 | ||
| 513 | pub fn openat(dirfd: i32, path: [*:0]const u8, flags: u32, mode: usize) usize { | 513 | pub fn openat(dirfd: i32, path: [*:0]const u8, flags: u32, mode: mode_t) usize { |
| 514 | // dirfd could be negative, for example AT_FDCWD is -100 | 514 | // dirfd could be negative, for example AT_FDCWD is -100 |
| 515 | return syscall4(.openat, @bitCast(usize, @as(isize, dirfd)), @ptrToInt(path), flags, mode); | 515 | return syscall4(.openat, @bitCast(usize, @as(isize, dirfd)), @ptrToInt(path), flags, mode); |
| 516 | } | 516 | } |
src/os.cpp+8| ... | @@ -1462,6 +1462,14 @@ static void init_rand() { | ... | @@ -1462,6 +1462,14 @@ static void init_rand() { |
| 1462 | unsigned seed; | 1462 | unsigned seed; |
| 1463 | memcpy(&seed, ptr_random, sizeof(seed)); | 1463 | memcpy(&seed, ptr_random, sizeof(seed)); |
| 1464 | srand(seed); | 1464 | srand(seed); |
| 1465 | #elif defined(ZIG_OS_FREEBSD) || defined(ZIG_OS_NETBSD) | ||
| 1466 | unsigned seed; | ||
| 1467 | size_t len = sizeof(seed); | ||
| 1468 | int mib[2] = { CTL_KERN, KERN_ARND }; | ||
| 1469 | if (sysctl(mib, 2, &seed, &len, NULL, 0) != 0) { | ||
| 1470 | zig_panic("unable to query random data from sysctl"); | ||
| 1471 | } | ||
| 1472 | srand(seed); | ||
| 1465 | #else | 1473 | #else |
| 1466 | int fd = open("/dev/urandom", O_RDONLY|O_CLOEXEC); | 1474 | int fd = open("/dev/urandom", O_RDONLY|O_CLOEXEC); |
| 1467 | if (fd == -1) { | 1475 | if (fd == -1) { |