git.lucas.co / cce-compositor
Wayland compositor (wlroots)
git clone https://git.lucas.co/cce-compositor.git

commit394660bff73924b8cae0e419c6ee5df352b72814
parentf0e89c4168
authorIsaac Freund <[email protected]>
date2020-08-01 13:40
server: use fork/execve for startup command

std.ChildProcess leaks an fd currently and is more complex than what we
need anyways.

 river/main.zig | 23 ++++++++++++-----------
 1 file changed, 12 insertions(+), 11 deletions(-)

diff --git a/river/main.zig b/river/main.zig
index 94eff88..0de1856 100644
--- a/river/main.zig
+++ b/river/main.zig
@@ -35,7 +35,7 @@ const usage: []const u8 =
 var server: Server = undefined;
 
 pub fn main() anyerror!void {
-    var startup_command: ?[]const u8 = null;
+    var startup_command: ?[*:0]const u8 = null;
     {
         var it = std.process.args();
         // Skip our name
@@ -47,7 +47,7 @@ pub fn main() anyerror!void {
                 std.os.exit(0);
             } else if (std.mem.eql(u8, arg, "-c")) {
                 if (it.nextPosix()) |command| {
-                    startup_command = command;
+                    startup_command = @ptrCast([*:0]const u8, command.ptr);
                 } else {
                     printErrorExit("Error: flag '-c' requires exactly one argument", .{});
                 }
@@ -85,16 +85,17 @@ pub fn main() anyerror!void {
 
     try server.start();
 
-    const startup_process = if (startup_command) |cmd| blk: {
-        const child_args = [_][]const u8{ "/bin/sh", "-c", cmd };
-        const child = try std.ChildProcess.init(&child_args, util.gpa);
-        try std.ChildProcess.spawn(child);
-        break :blk child;
+    const child_pid = if (startup_command) |cmd| blk: {
+        const child_args = [_:null]?[*:0]const u8{ "/bin/sh", "-c", cmd, null };
+        const pid = try std.os.fork();
+        if (pid == 0) {
+            if (std.os.system.sigprocmask(std.os.SIG_SETMASK, &std.os.empty_sigset, null) < 0) unreachable;
+            std.os.execveZ("/bin/sh", &child_args, std.c.environ) catch c._exit(1);
+        }
+        break :blk pid;
     } else null;
-    defer if (startup_process) |child| {
-        _ = child.kill() catch |e| log.err(.server, "failed to terminate startup process: {}", .{e});
-        child.deinit();
-    };
+    defer if (child_pid) |pid|
+        std.os.kill(pid, std.os.SIGTERM) catch |e| log.err(.server, "failed to kill startup process: {}", .{e});
 
     log.info(.server, "running...", .{});