diff --git a/src/bun.js/ModuleLoader.zig b/src/bun.js/ModuleLoader.zig index ac65cbc4b7..3479e54daa 100644 --- a/src/bun.js/ModuleLoader.zig +++ b/src/bun.js/ModuleLoader.zig @@ -30,45 +30,19 @@ pub fn resetArena(this: *ModuleLoader, jsc_vm: *VirtualMachine) void { } } -fn resolveEmbeddedNodeFileViaMemfd(file: *bun.StandaloneModuleGraph.File, path_buffer: *bun.PathBuffer, fd: *i32) ![]const u8 { - var label_buf: [128]u8 = undefined; - const count = struct { - pub var counter = std.atomic.Value(u32).init(0); - pub fn get() u32 { - return counter.fetchAdd(1, .seq_cst); - } - }.get(); - const label = std.fmt.bufPrintZ(&label_buf, "node-addon-{d}", .{count}) catch ""; - const memfd = try bun.sys.memfd_create(label, .executable).unwrap(); - errdefer memfd.close(); - - fd.* = @intCast(memfd.cast()); - errdefer fd.* = -1; - - try bun.sys.ftruncate(memfd, @intCast(file.contents.len)).unwrap(); - try bun.sys.File.writeAll(.{ .handle = memfd }, file.contents).unwrap(); - - return try std.fmt.bufPrint(path_buffer, "/proc/self/fd/{d}", .{memfd.cast()}); -} - -pub fn resolveEmbeddedFile(vm: *VirtualMachine, path_buf: *bun.PathBuffer, linux_memfd: *i32, input_path: []const u8, extname: []const u8) ?[]const u8 { +pub fn resolveEmbeddedFile(vm: *VirtualMachine, path_buf: *bun.PathBuffer, input_path: []const u8, extname: []const u8) ?[]const u8 { if (input_path.len == 0) return null; var graph = vm.standalone_module_graph orelse return null; const file = graph.find(input_path) orelse return null; if (comptime Environment.isLinux) { - // Best-effort: use memfd to avoid hitting the disk - if (resolveEmbeddedNodeFileViaMemfd(file, path_buf, linux_memfd)) |path| { - return path; - } else |_| { - // fall back to temp file - } + // TODO: use /proc/fd/12346 instead! Avoid the copy! } // atomically write to a tmpfile and then move it to the final destination - const tmpname_buf = bun.path_buffer_pool.get(); - defer bun.path_buffer_pool.put(tmpname_buf); - const tmpfilename = bun.fs.FileSystem.tmpname(extname, tmpname_buf, bun.hash(file.name)) catch return null; + var tmpname_buf: bun.PathBuffer = undefined; + const tmpfilename = bun.fs.FileSystem.tmpname(extname, &tmpname_buf, bun.hash(file.name)) catch return null; + const tmpdir: bun.FD = .fromStdDir(bun.fs.FileSystem.instance.tmpdir() catch return null); // First we open the tmpfile, to avoid any other work in the event of failure. @@ -76,7 +50,7 @@ pub fn resolveEmbeddedFile(vm: *VirtualMachine, path_buf: *bun.PathBuffer, linux defer tmpfile.fd.close(); switch (bun.api.node.fs.NodeFS.writeFileWithPathBuffer( - tmpname_buf, // not used + &tmpname_buf, // not used .{ .data = .{ @@ -1326,14 +1300,14 @@ pub const FetchFlags = enum { }; /// Support embedded .node files -export fn Bun__resolveEmbeddedNodeFile(vm: *VirtualMachine, in_out_str: *bun.String, linux_memfd_fd_to_close: *i32) bool { +export fn Bun__resolveEmbeddedNodeFile(vm: *VirtualMachine, in_out_str: *bun.String) bool { if (vm.standalone_module_graph == null) return false; const input_path = in_out_str.toUTF8(bun.default_allocator); defer input_path.deinit(); - const path_buffer = bun.path_buffer_pool.get(); - defer bun.path_buffer_pool.put(path_buffer); - const result = ModuleLoader.resolveEmbeddedFile(vm, path_buffer, linux_memfd_fd_to_close, input_path.slice(), "node") orelse return false; + const path_buf = bun.path_buffer_pool.get(); + defer bun.path_buffer_pool.put(path_buf); + const result = ModuleLoader.resolveEmbeddedFile(vm, path_buf, input_path.slice(), "node") orelse return false; in_out_str.* = bun.String.cloneUTF8(result); return true; } diff --git a/src/bun.js/api/ffi.zig b/src/bun.js/api/ffi.zig index d9c4d464dd..feae28a571 100644 --- a/src/bun.js/api/ffi.zig +++ b/src/bun.js/api/ffi.zig @@ -1013,21 +1013,10 @@ pub const FFI = struct { var filepath_buf = bun.path_buffer_pool.get(); defer bun.path_buffer_pool.put(filepath_buf); - var linux_memfd_to_close: i32 = -1; - defer { - if (Environment.isLinux) { - if (linux_memfd_to_close != -1) { - _ = bun.FD.fromSystem(linux_memfd_to_close).close(); - } - } else { - bun.debugAssert(linux_memfd_to_close == -1); - } - } const name = brk: { if (jsc.ModuleLoader.resolveEmbeddedFile( vm, filepath_buf, - &linux_memfd_to_close, name_slice.slice(), switch (Environment.os) { .linux => "so", @@ -1036,6 +1025,7 @@ pub const FFI = struct { .wasm => @compileError("TODO"), }, )) |resolved| { + @memcpy(filepath_buf[0..resolved.len], resolved); filepath_buf[resolved.len] = 0; break :brk filepath_buf[0..resolved.len]; } diff --git a/src/bun.js/bindings/BunProcess.cpp b/src/bun.js/bindings/BunProcess.cpp index 907682c237..2c4dc2f2a2 100644 --- a/src/bun.js/bindings/BunProcess.cpp +++ b/src/bun.js/bindings/BunProcess.cpp @@ -296,7 +296,7 @@ JSC_DEFINE_CUSTOM_SETTER(Process_defaultSetter, (JSC::JSGlobalObject * globalObj return true; } -extern "C" bool Bun__resolveEmbeddedNodeFile(void*, BunString*, int32_t*); +extern "C" bool Bun__resolveEmbeddedNodeFile(void*, BunString*); #if OS(WINDOWS) extern "C" HMODULE Bun__LoadLibraryBunString(BunString*); #endif @@ -434,7 +434,6 @@ JSC_DEFINE_HOST_FUNCTION(Process_functionDlopen, (JSC::JSGlobalObject * globalOb } CString utf8; - int32_t linuxMemfdToClose = -1; // Support embedded .node files // See StandaloneModuleGraph.zig for what this "$bunfs" thing is @@ -446,7 +445,7 @@ JSC_DEFINE_HOST_FUNCTION(Process_functionDlopen, (JSC::JSGlobalObject * globalOb bool deleteAfter = false; if (filename.startsWith(StandaloneModuleGraph__base_path)) { BunString bunStr = Bun::toString(filename); - if (Bun__resolveEmbeddedNodeFile(globalObject->bunVM(), &bunStr, &linuxMemfdToClose)) { + if (Bun__resolveEmbeddedNodeFile(globalObject->bunVM(), &bunStr)) { filename = bunStr.transferToWTFString(); deleteAfter = !filename.startsWith("/proc/"_s); } @@ -482,20 +481,11 @@ JSC_DEFINE_HOST_FUNCTION(Process_functionDlopen, (JSC::JSGlobalObject * globalOb delete[] dupeZ; } } - ASSERT(linuxMemfdToClose == -1); #else if (deleteAfter) { deleteAfter = false; Bun__unlink(utf8.data(), utf8.length()); } -#if OS(LINUX) - if (linuxMemfdToClose != -1) { - close(linuxMemfdToClose); - linuxMemfdToClose = -1; - } -#else - ASSERT(linuxMemfdToClose == -1); -#endif #endif }; diff --git a/src/sys.zig b/src/sys.zig index 0dd4ce8392..8b04a26128 100644 --- a/src/sys.zig +++ b/src/sys.zig @@ -3011,6 +3011,7 @@ pub const MemfdFlags = enum(u32) { const MFD_CLOEXEC: u32 = std.os.linux.MFD.CLOEXEC; const MFD_ALLOW_SEALING: u32 = std.os.linux.MFD.ALLOW_SEALING; }; + pub fn memfd_create(name: [:0]const u8, flags_: MemfdFlags) Maybe(bun.FileDescriptor) { if (comptime !Environment.isLinux) @compileError("linux only!"); var flags: u32 = @intFromEnum(flags_);