aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIsaac Freund <ifreund@ifreund.xyz>2020-07-08 14:00:51 +0200
committerIsaac Freund <ifreund@ifreund.xyz>2020-07-08 14:00:51 +0200
commitcbf645d468399456eee681d592066fb4afa55169 (patch)
treeec6740f05b108007d2835108ed32424fd29ff72c
parentd77ac5ac7a5c7801fb1099447f2158591b7c27fd (diff)
downloadriver-cbf645d468399456eee681d592066fb4afa55169.tar.gz
river-cbf645d468399456eee681d592066fb4afa55169.tar.xz
command/spawn: clean up and disown children
- Call setsid - Clean up the signal mask. - Use a double fork so that processes get inherited by init.
-rw-r--r--river/c.zig5
-rw-r--r--river/command/spawn.zig34
2 files changed, 29 insertions, 10 deletions
diff --git a/river/c.zig b/river/c.zig
index 829bdb7..dacb06e 100644
--- a/river/c.zig
+++ b/river/c.zig
@@ -19,9 +19,12 @@ pub usingnamespace @cImport({
@cDefine("_POSIX_C_SOURCE", "200809L");
@cDefine("WLR_USE_UNSTABLE", {});
- @cInclude("time.h");
@cInclude("stdlib.h");
+ @cInclude("time.h");
+ @cInclude("unistd.h");
+
@cInclude("linux/input-event-codes.h");
+
@cInclude("wayland-server-core.h");
//@cInclude("wlr/backend.h");
//@cInclude("wlr/render/wlr_renderer.h");
diff --git a/river/command/spawn.zig b/river/command/spawn.zig
index 96e25cd..fdc3ccb 100644
--- a/river/command/spawn.zig
+++ b/river/command/spawn.zig
@@ -17,6 +17,8 @@
const std = @import("std");
+const c = @import("../c.zig");
+
const Error = @import("../command.zig").Error;
const Seat = @import("../Seat.zig");
@@ -31,17 +33,31 @@ pub fn spawn(
const cmd = try std.mem.join(allocator, " ", args[1..]);
defer allocator.free(cmd);
+ const cmdZ = try std.cstr.addNullByte(allocator, cmd);
+ defer allocator.free(cmdZ);
- const child_args = [_][]const u8{ "/bin/sh", "-c", cmd };
- const child = try std.ChildProcess.init(&child_args, allocator);
- defer child.deinit();
+ const child_args = [_:null]?[*:0]const u8{ "/bin/sh", "-c", cmdZ, null };
- std.ChildProcess.spawn(child) catch |err| {
- out.* = try std.fmt.allocPrint(
- allocator,
- "failed to spawn {}: {}.",
- .{ cmd, err },
- );
+ const pid = std.os.fork() catch {
+ out.* = try std.fmt.allocPrint(allocator, "fork/execve failed", .{});
return Error.Other;
};
+
+ if (pid == 0) {
+ // Clean things up for the child in an intermediate fork
+ if (c.setsid() < 0) unreachable;
+ if (std.os.system.sigprocmask(std.os.SIG_SETMASK, &std.os.empty_sigset, null) < 0) unreachable;
+
+ const pid2 = std.os.fork() catch std.os.exit(1);
+ if (pid2 == 0) std.os.execveZ("/bin/sh", &child_args, std.c.environ) catch std.os.exit(1);
+
+ std.os.exit(0);
+ }
+
+ // Wait the intermediate child.
+ const status = std.os.waitpid(pid, 0);
+ if (std.os.WIFEXITED(status) and std.os.WEXITSTATUS(status) != 0) {
+ out.* = try std.fmt.allocPrint(allocator, "fork/execve failed", .{});
+ return Error.Other;
+ }
}