layout: use fork/execve instead of ChildProcess

This keeps things simpler, and we will need this control anyways in
order to enforce a timeout.
This commit is contained in:
Isaac Freund 2020-08-01 18:37:06 +02:00
parent 05557086e6
commit 845fcad9e6
No known key found for this signature in database
GPG Key ID: 86DED400DDFD7A11

View File

@ -232,32 +232,34 @@ fn layoutExternal(self: *Self, visible_count: u32) !void {
defer arena.deinit(); defer arena.deinit();
// Assemble command // Assemble command
const layout_command = std.fmt.allocPrint(&arena.allocator, "{} {} {} {d} {} {}", .{ const layout_command = try std.fmt.allocPrint0(&arena.allocator, "{} {} {} {d} {} {}", .{
self.layout, self.layout,
visible_count, visible_count,
self.master_count, self.master_count,
self.master_factor, self.master_factor,
layout_width, layout_width,
layout_height, layout_height,
}) catch @panic("Out of memory."); });
const cmd = [_][]const u8{ "/bin/sh", "-c", layout_command }; const cmd = [_:null]?[*:0]const u8{ "/bin/sh", "-c", layout_command, null };
const stdout_pipe = try std.os.pipe();
// Execute layout executable const pid = try std.os.fork();
// TODO abort after 1 second if (pid == 0) {
const child = try std.ChildProcess.init(&cmd, &arena.allocator); std.os.dup2(stdout_pipe[1], std.os.STDOUT_FILENO) catch c._exit(1);
child.stdin_behavior = .Ignore; std.os.close(stdout_pipe[0]);
child.stdout_behavior = .Pipe; std.os.close(stdout_pipe[1]);
try std.ChildProcess.spawn(child); std.os.execveZ("/bin/sh", &cmd, std.c.environ) catch c._exit(1);
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;
}
},
} }
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 // Parse layout command output
var view_boxen = std.ArrayList(Box).init(&arena.allocator); var view_boxen = std.ArrayList(Box).init(&arena.allocator);