authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-05-02 14:16:59-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-05-02 14:16:59-04:00
log7998e2b0f41bff86d8fbbb8112dd6c629d47e849
tree9f7bca5991f9fcdb291da10e2c830a749769dfad
parent5656f5090d8646e076db50da03cfc6ae686eb76b
parent8ebcca6734e07aea29098ca4c63c0216b3099d0e

Merge remote-tracking branch 'origin/master' into FireFox317-windows-evented-io


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-*
14sudo rm -rf /usr/local/*14sudo rm -rf /usr/local/*
15sudo apt-get install -y libxml2-dev libclang-10-dev llvm-10 llvm-10-dev liblld-10-dev cmake s3cmd gcc-7 g++-715sudo apt-get install -y libxml2-dev libclang-10-dev llvm-10 llvm-10-dev liblld-10-dev cmake s3cmd gcc-7 g++-7
1616
17QEMUBASE="qemu-linux-x86_64-5.0.0"17QEMUBASE="qemu-linux-x86_64-5.0.0-z2"
18wget https://ziglang.org/deps/$QEMUBASE.tar.xz18wget https://ziglang.org/deps/$QEMUBASE.tar.xz
19tar xf $QEMUBASE.tar.xz19tar xf $QEMUBASE.tar.xz
20PATH=$PWD/$QEMUBASE/bin:$PATH20PATH=$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;
9pub const dl_iterate_phdr_callback = extern fn (info: *dl_phdr_info, size: usize, data: ?*c_void) c_int;9pub const dl_iterate_phdr_callback = extern fn (info: *dl_phdr_info, size: usize, data: ?*c_void) c_int;
10pub extern "c" fn dl_iterate_phdr(callback: dl_iterate_phdr_callback, data: ?*c_void) c_int;10pub extern "c" fn dl_iterate_phdr(callback: dl_iterate_phdr_callback, data: ?*c_void) c_int;
1111
12pub extern "c" fn arc4random_buf(buf: [*]u8, len: usize) void;
12pub extern "c" fn __fstat50(fd: fd_t, buf: *Stat) c_int;13pub extern "c" fn __fstat50(fd: fd_t, buf: *Stat) c_int;
13pub extern "c" fn __stat50(path: [*:0]const u8, buf: *Stat) c_int;14pub extern "c" fn __stat50(path: [*:0]const u8, buf: *Stat) c_int;
14pub extern "c" fn __clock_gettime50(clk_id: c_int, tp: *timespec) c_int;15pub 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 }
468468
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 }
472480
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 }
476492
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 }
480505
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 }
496520
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 }
513536
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 }
528550
...@@ -679,7 +701,7 @@ pub const Loop = struct {...@@ -679,7 +701,7 @@ pub const Loop = struct {
679 }701 }
680702
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 }
701723
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 that1449/// 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.
1452pub fn deleteFileAbsolute(absolute_path: []const u8) DeleteFileError!void {1452pub 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 {
1457pub const deleteFileAbsoluteC = @compileError("deprecated: renamed to deleteFileAbsoluteZ");1457pub const deleteFileAbsoluteC = @compileError("deprecated: renamed to deleteFileAbsoluteZ");
14581458
1459/// Same as `deleteFileAbsolute` except the parameter is null-terminated.1459/// Same as `deleteFileAbsolute` except the parameter is null-terminated.
1460pub fn deleteFileAbsoluteZ(absolute_path_c: [*:0]const u8) DeleteFileError!void {1460pub 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}
14641464
1465/// Same as `deleteFileAbsolute` except the parameter is WTF-16 encoded.1465/// Same as `deleteFileAbsolute` except the parameter is WTF-16 encoded.
1466pub fn deleteFileAbsoluteW(absolute_path_w: [*:0]const u16) DeleteFileError!void {1466pub 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}
112112
113test "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
113const FileLockTestContext = struct {129const 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{
854858
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`.
857pub fn open(file_path: []const u8, flags: u32, perm: usize) OpenError!fd_t {861pub 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");
867871
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`.
870pub fn openZ(file_path: [*:0]const u8, flags: u32, perm: usize) OpenError!fd_t {874pub 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}
494494
495pub fn open(path: [*:0]const u8, flags: u32, perm: usize) usize {495pub 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}
508508
509pub fn create(path: [*:0]const u8, perm: usize) usize {509pub 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}
512512
513pub fn openat(dirfd: i32, path: [*:0]const u8, flags: u32, mode: usize) usize {513pub fn openat(dirfd: i32, path: [*:0]const u8, flags: u32, mode: mode_t) usize {
514 // dirfd could be negative, for example AT_FDCWD is -100514 // 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#else1473#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) {