| author | |
| committer | |
| log | 1eb8fe7c61d1de3b23afb00c0bb4729f3a0b037f |
| tree | 53021761cebbf7e7ddb53d77617b104fac54804f |
| parent | 2a02c7a0d59e25bac07a6ed2948a29438fb05527 |
| parent | 4b26c49076a1c163e5fdd1bd3a657e0794e5a917 |
Reviewed-on: https://codeberg.org/ziglang/zig/pulls/30626
Reviewed-by: Andrew Kelley <andrewrk@noreply.codeberg.org>6 files changed, 97 insertions(+), 11 deletions(-)
lib/compiler/test_runner.zig+10-6| ... | @@ -66,13 +66,13 @@ pub fn main() void { | ... | @@ -66,13 +66,13 @@ pub fn main() void { |
| 66 | } | 66 | } |
| 67 | 67 | ||
| 68 | if (listen) { | 68 | if (listen) { |
| 69 | return mainServer() catch @panic("internal test runner failure"); | 69 | return mainServer(args) catch @panic("internal test runner failure"); |
| 70 | } else { | 70 | } else { |
| 71 | return mainTerminal(); | 71 | return mainTerminal(args); |
| 72 | } | 72 | } |
| 73 | } | 73 | } |
| 74 | 74 | ||
| 75 | fn mainServer() !void { | 75 | fn mainServer(args: []const [:0]const u8) !void { |
| 76 | @disableInstrumentation(); | 76 | @disableInstrumentation(); |
| 77 | var stdin_reader = Io.File.stdin().readerStreaming(runner_threaded_io, &stdin_buffer); | 77 | var stdin_reader = Io.File.stdin().readerStreaming(runner_threaded_io, &stdin_buffer); |
| 78 | var stdout_writer = Io.File.stdout().writerStreaming(runner_threaded_io, &stdout_buffer); | 78 | var stdout_writer = Io.File.stdout().writerStreaming(runner_threaded_io, &stdout_buffer); |
| ... | @@ -131,7 +131,9 @@ fn mainServer() !void { | ... | @@ -131,7 +131,9 @@ fn mainServer() !void { |
| 131 | 131 | ||
| 132 | .run_test => { | 132 | .run_test => { |
| 133 | testing.allocator_instance = .{}; | 133 | testing.allocator_instance = .{}; |
| 134 | testing.io_instance = .init(testing.allocator, .{}); | 134 | testing.io_instance = .init(testing.allocator, .{ |
| 135 | .argv0 = if (@hasField(Io.Threaded.Argv0, "value")) .{ .value = args[0] } else .{}, | ||
| 136 | }); | ||
| 135 | log_err_count = 0; | 137 | log_err_count = 0; |
| 136 | const index = try server.receiveBody_u32(); | 138 | const index = try server.receiveBody_u32(); |
| 137 | const test_fn = builtin.test_functions[index]; | 139 | const test_fn = builtin.test_functions[index]; |
| ... | @@ -215,7 +217,7 @@ fn mainServer() !void { | ... | @@ -215,7 +217,7 @@ fn mainServer() !void { |
| 215 | } | 217 | } |
| 216 | } | 218 | } |
| 217 | 219 | ||
| 218 | fn mainTerminal() void { | 220 | fn mainTerminal(args: []const [:0]const u8) void { |
| 219 | @disableInstrumentation(); | 221 | @disableInstrumentation(); |
| 220 | if (builtin.fuzz) @panic("fuzz test requires server"); | 222 | if (builtin.fuzz) @panic("fuzz test requires server"); |
| 221 | 223 | ||
| ... | @@ -233,7 +235,9 @@ fn mainTerminal() void { | ... | @@ -233,7 +235,9 @@ fn mainTerminal() void { |
| 233 | var leaks: usize = 0; | 235 | var leaks: usize = 0; |
| 234 | for (test_fn_list, 0..) |test_fn, i| { | 236 | for (test_fn_list, 0..) |test_fn, i| { |
| 235 | testing.allocator_instance = .{}; | 237 | testing.allocator_instance = .{}; |
| 236 | testing.io_instance = .init(testing.allocator, .{}); | 238 | testing.io_instance = .init(testing.allocator, .{ |
| 239 | .argv0 = if (@hasField(Io.Threaded.Argv0, "value")) .{ .value = args[0] } else .{}, | ||
| 240 | }); | ||
| 237 | defer { | 241 | defer { |
| 238 | testing.io_instance.deinit(); | 242 | testing.io_instance.deinit(); |
| 239 | if (testing.allocator_instance.deinit() == .leak) leaks += 1; | 243 | if (testing.allocator_instance.deinit() == .leak) leaks += 1; |
lib/std/Io/Dir.zig+1| ... | @@ -113,6 +113,7 @@ pub const Reader = struct { | ... | @@ -113,6 +113,7 @@ pub const Reader = struct { |
| 113 | }, | 113 | }, |
| 114 | .wasi => @sizeOf(std.os.wasi.dirent_t) + | 114 | .wasi => @sizeOf(std.os.wasi.dirent_t) + |
| 115 | std.mem.alignForward(usize, max_name_bytes, @alignOf(std.os.wasi.dirent_t)), | 115 | std.mem.alignForward(usize, max_name_bytes, @alignOf(std.os.wasi.dirent_t)), |
| 116 | .openbsd => std.c.S.BLKSIZE, | ||
| 116 | else => if (builtin.link_libc) @sizeOf(std.c.dirent) else std.mem.alignForward(usize, max_name_bytes, @alignOf(usize)), | 117 | else => if (builtin.link_libc) @sizeOf(std.c.dirent) else std.mem.alignForward(usize, max_name_bytes, @alignOf(usize)), |
| 117 | }; | 118 | }; |
| 118 | 119 |
lib/std/Io/Threaded.zig+63| ... | @@ -390,6 +390,52 @@ const Thread = struct { | ... | @@ -390,6 +390,52 @@ const Thread = struct { |
| 390 | else => unreachable, | 390 | else => unreachable, |
| 391 | }; | 391 | }; |
| 392 | }, | 392 | }, |
| 393 | .openbsd => { | ||
| 394 | var tm: std.c.timespec = undefined; | ||
| 395 | var tm_ptr: ?*const std.c.timespec = null; | ||
| 396 | if (timeout_ns) |ns| { | ||
| 397 | tm_ptr = &tm; | ||
| 398 | tm = timestampToPosix(ns); | ||
| 399 | } | ||
| 400 | if (thread) |t| try t.beginSyscall(); | ||
| 401 | const rc = std.c.futex( | ||
| 402 | ptr, | ||
| 403 | std.c.FUTEX.WAIT | std.c.FUTEX.PRIVATE_FLAG, | ||
| 404 | @as(c_int, @bitCast(expect)), | ||
| 405 | tm_ptr, | ||
| 406 | null, // uaddr2 is ignored | ||
| 407 | ); | ||
| 408 | if (thread) |t| t.endSyscall(); | ||
| 409 | if (is_debug) switch (posix.errno(rc)) { | ||
| 410 | .SUCCESS => {}, | ||
| 411 | .NOSYS => unreachable, // constant op known good value | ||
| 412 | .AGAIN => {}, // contents of uaddr != val | ||
| 413 | .INVAL => unreachable, // invalid timeout | ||
| 414 | .TIMEDOUT => {}, // timeout | ||
| 415 | .INTR => {}, // a signal arrived | ||
| 416 | .CANCELED => {}, // a signal arrived and SA_RESTART was set | ||
| 417 | else => unreachable, | ||
| 418 | }; | ||
| 419 | }, | ||
| 420 | .dragonfly => { | ||
| 421 | var timeout_us: c_int = undefined; | ||
| 422 | if (timeout_ns) |ns| { | ||
| 423 | timeout_us = std.math.cast(c_int, ns / std.time.ns_per_us) orelse std.math.maxInt(c_int); | ||
| 424 | } else { | ||
| 425 | timeout_us = 0; | ||
| 426 | } | ||
| 427 | if (thread) |t| try t.beginSyscall(); | ||
| 428 | const rc = std.c.umtx_sleep(@ptrCast(ptr), @bitCast(expect), timeout_us); | ||
| 429 | if (thread) |t| t.endSyscall(); | ||
| 430 | if (is_debug) switch (std.posix.errno(rc)) { | ||
| 431 | .SUCCESS => {}, | ||
| 432 | .BUSY => {}, // ptr != expect | ||
| 433 | .AGAIN => {}, // maybe timed out, or paged out, or hit 2s kernel refresh | ||
| 434 | .INTR => {}, // spurious wake | ||
| 435 | .INVAL => unreachable, // invalid timeout | ||
| 436 | else => unreachable, | ||
| 437 | }; | ||
| 438 | }, | ||
| 393 | else => if (std.Thread.use_pthreads) { | 439 | else => if (std.Thread.use_pthreads) { |
| 394 | // TODO integrate the following function being called with robust cancelation. | 440 | // TODO integrate the following function being called with robust cancelation. |
| 395 | return pthreads_futex.wait(ptr, expect, timeout_ns) catch |err| switch (err) { | 441 | return pthreads_futex.wait(ptr, expect, timeout_ns) catch |err| switch (err) { |
| ... | @@ -473,6 +519,23 @@ const Thread = struct { | ... | @@ -473,6 +519,23 @@ const Thread = struct { |
| 473 | else => unreachable, // deadlock due to operating system bug | 519 | else => unreachable, // deadlock due to operating system bug |
| 474 | } | 520 | } |
| 475 | }, | 521 | }, |
| 522 | .openbsd => { | ||
| 523 | const rc = std.c.futex( | ||
| 524 | ptr, | ||
| 525 | std.c.FUTEX.WAKE | std.c.FUTEX.PRIVATE_FLAG, | ||
| 526 | @min(max_waiters, std.math.maxInt(c_int)), | ||
| 527 | null, // timeout is ignored | ||
| 528 | null, // uaddr2 is ignored | ||
| 529 | ); | ||
| 530 | assert(rc >= 0); | ||
| 531 | }, | ||
| 532 | .dragonfly => { | ||
| 533 | // will generally return 0 unless the address is bad | ||
| 534 | _ = std.c.umtx_wakeup( | ||
| 535 | @ptrCast(ptr), | ||
| 536 | @min(max_waiters, std.math.maxInt(c_int)), | ||
| 537 | ); | ||
| 538 | }, | ||
| 476 | else => if (std.Thread.use_pthreads) { | 539 | else => if (std.Thread.use_pthreads) { |
| 477 | return pthreads_futex.wake(ptr, max_waiters); | 540 | return pthreads_futex.wake(ptr, max_waiters); |
| 478 | } else { | 541 | } else { |
lib/std/c.zig+15| ... | @@ -167,6 +167,18 @@ pub const timespec = switch (native_os) { | ... | @@ -167,6 +167,18 @@ pub const timespec = switch (native_os) { |
| 167 | .openbsd, .haiku => extern struct { | 167 | .openbsd, .haiku => extern struct { |
| 168 | sec: time_t, | 168 | sec: time_t, |
| 169 | nsec: isize, | 169 | nsec: isize, |
| 170 | |||
| 171 | /// For use with `utimensat` and `futimens`. | ||
| 172 | pub const NOW: timespec = .{ | ||
| 173 | .sec = 0, // ignored | ||
| 174 | .nsec = -2, | ||
| 175 | }; | ||
| 176 | |||
| 177 | /// For use with `utimensat` and `futimens`. | ||
| 178 | pub const OMIT: timespec = .{ | ||
| 179 | .sec = 0, // ignored | ||
| 180 | .nsec = -1, | ||
| 181 | }; | ||
| 170 | }, | 182 | }, |
| 171 | else => void, | 183 | else => void, |
| 172 | }; | 184 | }; |
| ... | @@ -2365,6 +2377,8 @@ pub const S = switch (native_os) { | ... | @@ -2365,6 +2377,8 @@ pub const S = switch (native_os) { |
| 2365 | pub const IWOTH = 0o002; | 2377 | pub const IWOTH = 0o002; |
| 2366 | pub const IXOTH = 0o001; | 2378 | pub const IXOTH = 0o001; |
| 2367 | 2379 | ||
| 2380 | pub const BLKSIZE = 512; | ||
| 2381 | |||
| 2368 | pub fn ISFIFO(m: u32) bool { | 2382 | pub fn ISFIFO(m: u32) bool { |
| 2369 | return m & IFMT == IFIFO; | 2383 | return m & IFMT == IFIFO; |
| 2370 | } | 2384 | } |
| ... | @@ -9676,6 +9690,7 @@ pub const NSIG = switch (native_os) { | ... | @@ -9676,6 +9690,7 @@ pub const NSIG = switch (native_os) { |
| 9676 | .illumos => 75, | 9690 | .illumos => 75, |
| 9677 | // https://github.com/SerenityOS/serenity/blob/046c23f567a17758d762a33bdf04bacbfd088f9f/Kernel/API/POSIX/signal_numbers.h#L42 | 9691 | // https://github.com/SerenityOS/serenity/blob/046c23f567a17758d762a33bdf04bacbfd088f9f/Kernel/API/POSIX/signal_numbers.h#L42 |
| 9678 | .openbsd, .serenity => 33, | 9692 | .openbsd, .serenity => 33, |
| 9693 | .dragonfly => 64, | ||
| 9679 | else => {}, | 9694 | else => {}, |
| 9680 | }; | 9695 | }; |
| 9681 | 9696 |
lib/std/fs/test.zig+3-1| ... | @@ -645,6 +645,7 @@ fn contains(entries: *const std.array_list.Managed(Dir.Entry), el: Dir.Entry) bo | ... | @@ -645,6 +645,7 @@ fn contains(entries: *const std.array_list.Managed(Dir.Entry), el: Dir.Entry) bo |
| 645 | 645 | ||
| 646 | test "Dir.realPath smoke test" { | 646 | test "Dir.realPath smoke test" { |
| 647 | if (native_os == .wasi) return error.SkipZigTest; | 647 | if (native_os == .wasi) return error.SkipZigTest; |
| 648 | if (native_os == .openbsd) return error.SkipZigTest; | ||
| 648 | 649 | ||
| 649 | try testWithAllSupportedPathTypes(struct { | 650 | try testWithAllSupportedPathTypes(struct { |
| 650 | fn impl(ctx: *TestContext) !void { | 651 | fn impl(ctx: *TestContext) !void { |
| ... | @@ -820,7 +821,7 @@ test "file operations on directories" { | ... | @@ -820,7 +821,7 @@ test "file operations on directories" { |
| 820 | try expectError(error.IsDir, ctx.dir.createFile(io, test_dir_name, .{})); | 821 | try expectError(error.IsDir, ctx.dir.createFile(io, test_dir_name, .{})); |
| 821 | try expectError(error.IsDir, ctx.dir.deleteFile(io, test_dir_name)); | 822 | try expectError(error.IsDir, ctx.dir.deleteFile(io, test_dir_name)); |
| 822 | switch (native_os) { | 823 | switch (native_os) { |
| 823 | .dragonfly, .netbsd => { | 824 | .netbsd => { |
| 824 | // no error when reading a directory. See https://github.com/ziglang/zig/issues/5732 | 825 | // no error when reading a directory. See https://github.com/ziglang/zig/issues/5732 |
| 825 | const buf = try ctx.dir.readFileAlloc(io, test_dir_name, testing.allocator, .unlimited); | 826 | const buf = try ctx.dir.readFileAlloc(io, test_dir_name, testing.allocator, .unlimited); |
| 826 | testing.allocator.free(buf); | 827 | testing.allocator.free(buf); |
| ... | @@ -1240,6 +1241,7 @@ test "createDirPath, put some files in it, deleteTreeMinStackSize" { | ... | @@ -1240,6 +1241,7 @@ test "createDirPath, put some files in it, deleteTreeMinStackSize" { |
| 1240 | 1241 | ||
| 1241 | test "createDirPath in a directory that no longer exists" { | 1242 | test "createDirPath in a directory that no longer exists" { |
| 1242 | if (native_os == .windows) return error.SkipZigTest; // Windows returns FileBusy if attempting to remove an open dir | 1243 | if (native_os == .windows) return error.SkipZigTest; // Windows returns FileBusy if attempting to remove an open dir |
| 1244 | if (native_os == .dragonfly) return error.SkipZigTest; // DragonflyBSD does not produce error (hammer2 fs) | ||
| 1243 | 1245 | ||
| 1244 | const io = testing.io; | 1246 | const io = testing.io; |
| 1245 | 1247 |
lib/std/posix/test.zig+5-4| ... | @@ -364,9 +364,10 @@ test "getrlimit and setrlimit" { | ... | @@ -364,9 +364,10 @@ test "getrlimit and setrlimit" { |
| 364 | } | 364 | } |
| 365 | 365 | ||
| 366 | test "sigrtmin/max" { | 366 | test "sigrtmin/max" { |
| 367 | if (native_os == .wasi or native_os == .windows or native_os.isDarwin() or native_os == .openbsd) { | 367 | if (native_os.isDarwin() or switch (native_os) { |
| 368 | return error.SkipZigTest; | 368 | .wasi, .windows, .openbsd, .dragonfly => true, |
| 369 | } | 369 | else => false, |
| 370 | }) return error.SkipZigTest; | ||
| 370 | 371 | ||
| 371 | try expect(posix.sigrtmin() >= 32); | 372 | try expect(posix.sigrtmin() >= 32); |
| 372 | try expect(posix.sigrtmin() >= posix.system.sigrtmin()); | 373 | try expect(posix.sigrtmin() >= posix.system.sigrtmin()); |
| ... | @@ -397,7 +398,7 @@ fn reserved_signo(i: usize) bool { | ... | @@ -397,7 +398,7 @@ fn reserved_signo(i: usize) bool { |
| 397 | if (!builtin.link_libc) return false; | 398 | if (!builtin.link_libc) return false; |
| 398 | const max = if (native_os == .netbsd) 32 else 31; | 399 | const max = if (native_os == .netbsd) 32 else 31; |
| 399 | if (i > max) return true; | 400 | if (i > max) return true; |
| 400 | if (native_os == .openbsd) return false; // no RT signals | 401 | if (native_os == .openbsd or native_os == .dragonfly) return false; // no RT signals |
| 401 | return i < posix.sigrtmin(); | 402 | return i < posix.sigrtmin(); |
| 402 | } | 403 | } |
| 403 | 404 |