diff options
| author | Isaac Freund <ifreund@ifreund.xyz> | 2020-08-01 18:37:06 +0200 |
|---|---|---|
| committer | Isaac Freund <ifreund@ifreund.xyz> | 2020-08-01 18:37:06 +0200 |
| commit | 845fcad9e6669935f4975c49b922785262b23578 (patch) | |
| tree | a07949d8a52382aaaf3c60deedca5f7569e8c760 | |
| parent | 05557086e604dc4bd39cc1a764bb06264ab032ac (diff) | |
| download | river-845fcad9e6669935f4975c49b922785262b23578.tar.gz river-845fcad9e6669935f4975c49b922785262b23578.tar.xz | |
layout: use fork/execve instead of ChildProcess
This keeps things simpler, and we will need this control anyways in
order to enforce a timeout.
| -rw-r--r-- | river/Output.zig | 40 |
1 files changed, 21 insertions, 19 deletions
diff --git a/river/Output.zig b/river/Output.zig index 78eddc7..48aa490 100644 --- a/river/Output.zig +++ b/river/Output.zig @@ -232,32 +232,34 @@ fn layoutExternal(self: *Self, visible_count: u32) !void { defer arena.deinit(); // Assemble command - const layout_command = std.fmt.allocPrint(&arena.allocator, "{} {} {} {d} {} {}", .{ + const layout_command = try std.fmt.allocPrint0(&arena.allocator, "{} {} {} {d} {} {}", .{ self.layout, visible_count, self.master_count, self.master_factor, layout_width, layout_height, - }) catch @panic("Out of memory."); - const cmd = [_][]const u8{ "/bin/sh", "-c", layout_command }; - - // Execute layout executable - // TODO abort after 1 second - const child = try std.ChildProcess.init(&cmd, &arena.allocator); - child.stdin_behavior = .Ignore; - child.stdout_behavior = .Pipe; - try std.ChildProcess.spawn(child); - const max_output_size = 400 * 1024; - const buffer = try child.stdout.?.inStream().readAllAlloc(&arena.allocator, max_output_size); - const term = try child.wait(); - switch (term) { - .Exited, .Signal, .Stopped, .Unknown => |code| { - if (code != 0) { - return LayoutError.BadExitCode; - } - }, + }); + const cmd = [_:null]?[*:0]const u8{ "/bin/sh", "-c", layout_command, null }; + const stdout_pipe = try std.os.pipe(); + + const pid = try std.os.fork(); + if (pid == 0) { + std.os.dup2(stdout_pipe[1], std.os.STDOUT_FILENO) catch c._exit(1); + std.os.close(stdout_pipe[0]); + std.os.close(stdout_pipe[1]); + std.os.execveZ("/bin/sh", &cmd, std.c.environ) catch c._exit(1); } + std.os.close(stdout_pipe[1]); + const stdout = std.fs.File{ .handle = stdout_pipe[0], .io_mode = std.io.mode }; + defer stdout.close(); + + // TODO abort after a timeout + const status = std.os.waitpid(pid, 0); + if (!std.os.WIFEXITED(status) or std.os.WEXITSTATUS(status) != 0) + return LayoutError.BadExitCode; + + const buffer = try stdout.inStream().readAllAlloc(&arena.allocator, 1024); // Parse layout command output var view_boxen = std.ArrayList(Box).init(&arena.allocator); |
