diff options
author | Himbeer <himbeer@disroot.org> | 2024-07-17 13:04:00 +0200 |
---|---|---|
committer | Himbeer <himbeer@disroot.org> | 2024-07-17 13:04:00 +0200 |
commit | 624954ef5fc395012825577abea46ec73d24ef6a (patch) | |
tree | 58f372d69867bff4ab10acccdcc4fb36417f53d6 | |
parent | ed35a9acf154f4b90b06602b648fe916ec442cc5 (diff) |
process: Detach or orphan provided resources on termination
Fixes #42.
-rw-r--r-- | src/lib/process.zig | 6 | ||||
-rw-r--r-- | src/lib/resources.zig | 12 | ||||
-rw-r--r-- | src/lib/syscall.zig | 60 | ||||
-rw-r--r-- | src/lib/sysexchange.zig | 6 | ||||
-rw-r--r-- | src/lib/vfs.zig | 53 |
5 files changed, 113 insertions, 24 deletions
diff --git a/src/lib/process.zig b/src/lib/process.zig index dcb1baa..a4bbb75 100644 --- a/src/lib/process.zig +++ b/src/lib/process.zig @@ -7,6 +7,7 @@ const std = @import("std"); const instructions = @import("instructions.zig"); const paging = @import("paging.zig"); +const sysexchange = @import("sysexchange.zig"); const time = @import("sbi/time.zig"); const trap = @import("trap.zig"); const vfs = @import("vfs.zig"); @@ -171,6 +172,10 @@ pub const Info = struct { var node = list.first; while (node) |proc_node| : (node = proc_node.next) { if (self.shouldRemove(&proc_node.data)) { + if (proc_node.data.thread_id != self.thread_id) { + proc_node.data.terminate(); + } + list.remove(proc_node); self.allocator.destroy(proc_node); } @@ -194,6 +199,7 @@ pub const Info = struct { cleanup_hook.cleanupFn(self, cleanup_hook.buffer, cleanup_hook.copy); } if (self.term_hook) |term_hook| { + sysexchange.frameReturn(void, &self.trap_frame, vfs.Error.Detached); term_hook.hookFn(term_hook.context, self); } } diff --git a/src/lib/resources.zig b/src/lib/resources.zig index c79c82e..f73c751 100644 --- a/src/lib/resources.zig +++ b/src/lib/resources.zig @@ -67,7 +67,9 @@ fn provideConsole() !void { .writeFn = iofs.debug.write, }, }, - }, 0); + }, 0, .{ + .reclaimable = false, + }); } fn provideUserinit() !void { @@ -110,7 +112,9 @@ fn addFile(path: []const u8, file: File) !void { .initializer = initializer, }, }, - }, 0); + }, 0, .{ + .reclaimable = false, + }); } fn addDir(path: []const u8) !void { @@ -121,7 +125,9 @@ fn addDir(path: []const u8) !void { try vfs.provideResource(path, .{ .tag = .dir, .data = .{ .dir = tree }, - }, 0); + }, 0, .{ + .reclaimable = false, + }); } fn open(initializer: ?*anyopaque, _: u16) callconv(.C) Result(*anyopaque) { diff --git a/src/lib/syscall.zig b/src/lib/syscall.zig index 661c98d..1533cd4 100644 --- a/src/lib/syscall.zig +++ b/src/lib/syscall.zig @@ -74,6 +74,7 @@ fn close(proc: *process.Info, trap_frame: *const trap.Frame) void { // provideStream( // path_c: [*:0]const u8, // fixme: Kernel panic if null pointer +// options: *const vfs.Options, // fixme: Kernel panic if null pointer // readFn: ?vfs.Stream.ReadFn, // writeFn: ?vfs.Stream.WriteFn, // ) Result(void) @@ -82,8 +83,9 @@ fn provideStream(proc: *const process.Info, trap_frame: *trap.Frame) void { defer paging.setUserMemoryAccess(false); const path_c: [*:0]const u8 = @ptrFromInt(trap_frame.general_purpose_registers[10]); - const readFn: ?vfs.Stream.ReadFn = @ptrFromInt(trap_frame.general_purpose_registers[11]); - const writeFn: ?vfs.Stream.WriteFn = @ptrFromInt(trap_frame.general_purpose_registers[12]); + const options: *const vfs.Options = @ptrFromInt(trap_frame.general_purpose_registers[11]); + const readFn: ?vfs.Stream.ReadFn = @ptrFromInt(trap_frame.general_purpose_registers[12]); + const writeFn: ?vfs.Stream.WriteFn = @ptrFromInt(trap_frame.general_purpose_registers[13]); sysexchange.frameReturn(null, trap_frame, vfs.provideResourceZ(path_c, .{ .tag = .stream, @@ -91,11 +93,12 @@ fn provideStream(proc: *const process.Info, trap_frame: *trap.Frame) void { .readFn = readFn, .writeFn = writeFn, } }, - }, proc.id)); + }, proc.id, options.*)); } // provideFile( // path_c: [*:0]const u8, // fixme: Kernel panic if null pointer +// options: *const vfs.Options, // fixme: Kernel panic if null pointer // openFn: vfs.File.OpenFn, // readFn: ?vfs.File.ReadFn, // writeFn: ?vfs.File.WriteFn, @@ -106,10 +109,11 @@ fn provideFile(proc: *const process.Info, trap_frame: *trap.Frame) void { defer paging.setUserMemoryAccess(false); const path_c: [*:0]const u8 = @ptrFromInt(trap_frame.general_purpose_registers[10]); - const openFn: vfs.File.OpenFn = @ptrFromInt(trap_frame.general_purpose_registers[11]); - const readFn: ?vfs.File.ReadFn = @ptrFromInt(trap_frame.general_purpose_registers[12]); - const writeFn: ?vfs.File.WriteFn = @ptrFromInt(trap_frame.general_purpose_registers[13]); - const closeFn: ?vfs.File.CloseFn = @ptrFromInt(trap_frame.general_purpose_registers[14]); + const options: *const vfs.Options = @ptrFromInt(trap_frame.general_purpose_registers[11]); + const openFn: vfs.File.OpenFn = @ptrFromInt(trap_frame.general_purpose_registers[12]); + const readFn: ?vfs.File.ReadFn = @ptrFromInt(trap_frame.general_purpose_registers[13]); + const writeFn: ?vfs.File.WriteFn = @ptrFromInt(trap_frame.general_purpose_registers[14]); + const closeFn: ?vfs.File.CloseFn = @ptrFromInt(trap_frame.general_purpose_registers[15]); sysexchange.frameReturn(null, trap_frame, vfs.provideResourceZ(path_c, .{ .tag = .file, @@ -120,11 +124,12 @@ fn provideFile(proc: *const process.Info, trap_frame: *trap.Frame) void { .closeFn = closeFn, .initializer = null, } }, - }, proc.id)); + }, proc.id, options.*)); } // provideHook( // path_c: [*:0]const u8, // fixme: Kernel panic if null pointer +// options: *const vfs.Options, // fixme: Kernel panic if null pointer, // callback: vfs.Hook.Callback, // ) Result(void) fn provideHook(proc: *const process.Info, trap_frame: *trap.Frame) void { @@ -132,14 +137,15 @@ fn provideHook(proc: *const process.Info, trap_frame: *trap.Frame) void { defer paging.setUserMemoryAccess(false); const path_c: [*:0]const u8 = @ptrFromInt(trap_frame.general_purpose_registers[10]); - const callback: vfs.Hook.Callback = @ptrFromInt(trap_frame.general_purpose_registers[11]); + const options: *const vfs.Options = @ptrFromInt(trap_frame.general_purpose_registers[11]); + const callback: vfs.Hook.Callback = @ptrFromInt(trap_frame.general_purpose_registers[12]); sysexchange.frameReturn(null, trap_frame, vfs.provideResourceZ(path_c, .{ .tag = .hook, .data = .{ .hook = .{ .callback = callback, } }, - }, proc.id)); + }, proc.id, options.*)); } // mkdir( @@ -158,11 +164,14 @@ fn mkdir(proc: *const process.Info, trap_frame: *trap.Frame) void { sysexchange.frameReturn(null, trap_frame, vfs.provideResourceZ(path_c, .{ .tag = .dir, .data = .{ .dir = tree }, - }, proc.id)); + }, proc.id, .{ + .reclaimable = false, + })); } // provideDirHook( // path_c: [*:0]const u8, // fixme: Kernel panic if null pointer +// options: *const vfs.Options, // fixme: Kernel panic if null pointer // provideFn: vfs.DirHook.ProvideFn, // findFn: vfs.DirHook.FindFn, // removeFn: vfs.DirHook.RemoveFn, @@ -172,9 +181,10 @@ fn provideDirHook(proc: *const process.Info, trap_frame: *trap.Frame) void { defer paging.setUserMemoryAccess(false); const path_c: [*:0]const u8 = @ptrFromInt(trap_frame.general_purpose_registers[10]); - const provideFn: vfs.DirHook.ProvideFn = @ptrFromInt(trap_frame.general_purpose_registers[11]); - const findFn: vfs.DirHook.FindFn = @ptrFromInt(trap_frame.general_purpose_registers[12]); - const removeFn: vfs.DirHook.RemoveFn = @ptrFromInt(trap_frame.general_purpose_registers[13]); + const options: *const vfs.Options = @ptrFromInt(trap_frame.general_purpose_registers[11]); + const provideFn: vfs.DirHook.ProvideFn = @ptrFromInt(trap_frame.general_purpose_registers[12]); + const findFn: vfs.DirHook.FindFn = @ptrFromInt(trap_frame.general_purpose_registers[13]); + const removeFn: vfs.DirHook.RemoveFn = @ptrFromInt(trap_frame.general_purpose_registers[14]); sysexchange.frameReturn(null, trap_frame, vfs.provideResourceZ(path_c, .{ .tag = .dir_hook, @@ -183,7 +193,7 @@ fn provideDirHook(proc: *const process.Info, trap_frame: *trap.Frame) void { .findFn = findFn, .removeFn = removeFn, } }, - }, proc.id)); + }, proc.id, options.*)); } // remove(path_c: [*:0]const u8) Result(void) // fixme: Kernel panic if null pointer @@ -225,7 +235,15 @@ fn read(proc: *process.Info, trap_frame: *trap.Frame) void { sysexchange.frameReturn(usize, trap_frame, process.Error.BadRdHandle); return; }; - sysexchange.frameReturn(usize, trap_frame, rd.read(proc, buffer[0..len])); + + const result = rd.read(proc, buffer[0..len]) catch |err| blk: { + if (err == vfs.Error.Orphaned) { + proc.destroyRdHandle(handle); + } + + break :blk err; + }; + sysexchange.frameReturn(usize, trap_frame, result); } // write(handle: usize, bytes: [*]const u8, len: usize) Result(usize) @@ -241,7 +259,15 @@ fn write(proc: *process.Info, trap_frame: *trap.Frame) void { sysexchange.frameReturn(usize, trap_frame, process.Error.BadRdHandle); return; }; - sysexchange.frameReturn(usize, trap_frame, rd.write(proc, bytes[0..len])); + + const result = rd.write(proc, bytes[0..len]) catch |err| blk: { + if (err == vfs.Error.Orphaned) { + proc.destroyRdHandle(handle); + } + + break :blk err; + }; + sysexchange.frameReturn(usize, trap_frame, result); } // terminate() noreturn diff --git a/src/lib/sysexchange.zig b/src/lib/sysexchange.zig index 3dd93df..c3d7fa4 100644 --- a/src/lib/sysexchange.zig +++ b/src/lib/sysexchange.zig @@ -63,6 +63,8 @@ pub const Status = enum(usize) { read_not_supported, write_not_supported, in_use, + detached, + orphaned, unknown = std.math.maxInt(usize), pub fn fromError(err: anyerror) Status { @@ -122,6 +124,8 @@ pub const Status = enum(usize) { error.ReadNotSupported => .read_not_supported, error.WriteNotSupported => .write_not_supported, error.InUse => .in_use, + error.Detached => .detached, + error.Orphaned => .orphaned, else => .unknown, }; } @@ -186,6 +190,8 @@ pub const Status = enum(usize) { .read_not_supported => error.ReadNotSupported, .write_not_supported => error.WriteNotSupported, .in_use => error.InUse, + .detached => error.Detached, + .orphaned => error.Orphaned, .unknown => error.Unknown, }; } diff --git a/src/lib/vfs.zig b/src/lib/vfs.zig index f3520be..c8cc552 100644 --- a/src/lib/vfs.zig +++ b/src/lib/vfs.zig @@ -10,7 +10,22 @@ const sysexchange = @import("sysexchange.zig"); const mem = std.mem; -var root: Node = .{ .data = .{ .name = "", .inode = .{ .resource = .{ .tag = .dir, .data = .{ .dir = undefined } }, .pid = 0 } } }; +var root: Node = .{ + .data = .{ + .name = "", + .inode = .{ + .resource = .{ + .tag = .dir, + .data = .{ .dir = undefined }, + }, + .pid = 0, + .options = .{ + .reclaimable = false, + }, + .flags = .{}, + }, + }, +}; pub fn treeRoot() *const Tree { return root.data.inode.resource.data.dir; @@ -25,6 +40,8 @@ pub const Error = error{ ReadNotSupported, WriteNotSupported, InUse, + Detached, + Orphaned, }; // A stream is a resource that provides a shared data stream with a driver. @@ -91,6 +108,16 @@ pub const Inode = extern struct { resource: Resource, refs: usize = 0, pid: u16, + options: Options, + flags: Flags, +}; + +pub const Options = extern struct { + reclaimable: bool, +}; + +pub const Flags = extern struct { + detached: bool = false, }; pub const DirEntry = struct { @@ -151,6 +178,13 @@ pub const ResourceDescriptor = struct { } pub fn read(self: ResourceDescriptor, proc: *process.Info, buffer: []u8) !usize { + if (self.inode.flags.detached and self.inode.options.reclaimable) { + return Error.Detached; + } + if (self.inode.flags.detached and !self.inode.options.reclaimable) { + return Error.Orphaned; + } + return switch (self.inode.resource.tag) { .stream => { const stream = self.inode.resource.data.stream; @@ -179,6 +213,13 @@ pub const ResourceDescriptor = struct { } pub fn write(self: ResourceDescriptor, proc: *process.Info, bytes: []const u8) !usize { + if (self.inode.flags.detached and self.inode.options.reclaimable) { + return Error.Detached; + } + if (self.inode.flags.detached and !self.inode.options.reclaimable) { + return Error.Orphaned; + } + return switch (self.inode.resource.tag) { .stream => { const stream = self.inode.resource.data.stream; @@ -256,7 +297,7 @@ pub fn find(path: []const u8) ?*Inode { return &root.data.inode; } -pub fn provideResource(path: []const u8, resource: Resource, pid: u16) !void { +pub fn provideResource(path: []const u8, resource: Resource, pid: u16, options: Options) !void { if (!std.fs.path.isAbsolutePosix(path)) return Error.RelativePathNotAllowed; const dirname = std.fs.path.dirnamePosix(path) orelse return Error.NoAbsoluteContainingDirectory; @@ -271,6 +312,8 @@ pub fn provideResource(path: []const u8, resource: Resource, pid: u16) !void { .inode = .{ .resource = resource, .pid = pid, + .options = options, + .flags = .{}, }, }); }, @@ -280,6 +323,8 @@ pub fn provideResource(path: []const u8, resource: Resource, pid: u16) !void { break :blk dir_hook.provideFn(basename.ptr, basename.len, .{ .resource = resource, .pid = pid, + .options = options, + .flags = .{}, }).toErrorUnion(); }, else => Error.NotADirectory, @@ -287,8 +332,8 @@ pub fn provideResource(path: []const u8, resource: Resource, pid: u16) !void { } else return Error.NotFound; } -pub fn provideResourceZ(path_c: [*:0]const u8, resource: Resource, pid: u16) !void { - return provideResource(mem.sliceTo(path_c, 0), resource, pid); +pub fn provideResourceZ(path_c: [*:0]const u8, resource: Resource, pid: u16, options: Options) !void { + return provideResource(mem.sliceTo(path_c, 0), resource, pid, options); } pub fn open(proc: *process.Info, path: []const u8, pid: u16, data: usize) !ResourceDescriptor { |