aboutsummaryrefslogtreecommitdiff
path: root/lib/std
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2019-12-31 16:34:14 -0500
committerAndrew Kelley <andrew@ziglang.org>2019-12-31 16:34:14 -0500
commit8186211404552a31eaf2a7bc182a46a7e40eacda (patch)
tree3e93cad370217a1a65fad5b3a91e91300f120123 /lib/std
parenta153a972adbe783bc8a0d08df0942a3bf0552188 (diff)
downloadzig-8186211404552a31eaf2a7bc182a46a7e40eacda.tar.gz
zig-8186211404552a31eaf2a7bc182a46a7e40eacda.zip
improvements to memfd_create
* move test from std/io/test.zig to std/os/test.zig * do glibc version check, and make direct system call if glibc is too old * disable test when not linking libc, to avoid not working with outdated qemu version on the CI server. see #4019
Diffstat (limited to 'lib/std')
-rw-r--r--lib/std/io/test.zig14
-rw-r--r--lib/std/os.zig16
-rw-r--r--lib/std/os/test.zig21
3 files changed, 34 insertions, 17 deletions
diff --git a/lib/std/io/test.zig b/lib/std/io/test.zig
index b572a7bf92..92259fd6e9 100644
--- a/lib/std/io/test.zig
+++ b/lib/std/io/test.zig
@@ -649,17 +649,3 @@ test "updateTimes" {
std.testing.expect(stat_new.atime < stat_old.atime);
std.testing.expect(stat_new.mtime < stat_old.mtime);
}
-
-test "memfd_create" {
- if (builtin.os != .linux) return error.SkipZigTest;
-
- const fd = try std.os.memfd_create("test", 0);
- defer std.os.close(fd);
- try std.os.write(fd, "test");
- try std.os.lseek_SET(fd, 0);
-
- var buf: [10]u8 = undefined;
- const bytes_read = try std.os.read(fd, &buf);
- expect(bytes_read == 4);
- expect(mem.eql(u8, buf[0..4], "test"));
-}
diff --git a/lib/std/os.zig b/lib/std/os.zig
index 31212e9b8b..b51dbe7d2a 100644
--- a/lib/std/os.zig
+++ b/lib/std/os.zig
@@ -3282,9 +3282,19 @@ pub fn setsockopt(fd: fd_t, level: u32, optname: u32, opt: []const u8) SetSockOp
}
}
+pub const MemFdCreateError = error{
+ SystemFdQuotaExceeded,
+ ProcessFdQuotaExceeded,
+ OutOfMemory,
+} || UnexpectedError;
+
pub fn memfd_createC(name: [*:0]const u8, flags: u32) !fd_t {
- const rc = system.memfd_create(name, flags);
- switch (errno(rc)) {
+ // memfd_create is available only in glibc versions starting with 2.27.
+ const use_c = std.c.versionCheck(.{ .major = 2, .minor = 27, .patch = 0 }).ok;
+ const sys = if (use_c) std.c else linux;
+ const getErrno = if (use_c) std.c.getErrno else linux.getErrno;
+ const rc = sys.memfd_create(name, flags);
+ switch (getErrno(rc)) {
0 => return @intCast(fd_t, rc),
EFAULT => unreachable, // name has invalid memory
EINVAL => unreachable, // name/flags are faulty
@@ -3308,5 +3318,5 @@ fn toMemFdPath(name: []const u8) ![MFD_MAX_NAME_LEN:0]u8 {
pub fn memfd_create(name: []const u8, flags: u32) !fd_t {
const name_t = try toMemFdPath(name);
- return try memfd_createC(&name_t, flags);
+ return memfd_createC(&name_t, flags);
}
diff --git a/lib/std/os/test.zig b/lib/std/os/test.zig
index f61e8b4657..16946660e4 100644
--- a/lib/std/os/test.zig
+++ b/lib/std/os/test.zig
@@ -237,3 +237,24 @@ test "argsAlloc" {
var args = try std.process.argsAlloc(std.heap.page_allocator);
std.process.argsFree(std.heap.page_allocator, args);
}
+
+test "memfd_create" {
+ // memfd_create is linux specific.
+ if (builtin.os != .linux) return error.SkipZigTest;
+ // Zig's CI testing infrastructure uses QEMU. Currently the version is
+ // qemu 2.11 from Ubuntu 18.04, which does not have memfd_create support.
+ // memfd_create support is introduced in qemu 4.2. To avoid
+ // "invalid syscall" errors from qemu, we disable the test when not linking libc.
+ // https://github.com/ziglang/zig/issues/4019
+ if (!builtin.link_libc) return error.SkipZigTest;
+
+ const fd = try std.os.memfd_create("test", 0);
+ defer std.os.close(fd);
+ try std.os.write(fd, "test");
+ try std.os.lseek_SET(fd, 0);
+
+ var buf: [10]u8 = undefined;
+ const bytes_read = try std.os.read(fd, &buf);
+ expect(bytes_read == 4);
+ expect(mem.eql(u8, buf[0..4], "test"));
+}