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.
This commit is contained in:
Isaac Freund 2020-07-08 14:00:51 +02:00
parent d77ac5ac7a
commit cbf645d468
No known key found for this signature in database
GPG Key ID: 86DED400DDFD7A11
2 changed files with 29 additions and 10 deletions

View File

@ -19,9 +19,12 @@ pub usingnamespace @cImport({
@cDefine("_POSIX_C_SOURCE", "200809L"); @cDefine("_POSIX_C_SOURCE", "200809L");
@cDefine("WLR_USE_UNSTABLE", {}); @cDefine("WLR_USE_UNSTABLE", {});
@cInclude("time.h");
@cInclude("stdlib.h"); @cInclude("stdlib.h");
@cInclude("time.h");
@cInclude("unistd.h");
@cInclude("linux/input-event-codes.h"); @cInclude("linux/input-event-codes.h");
@cInclude("wayland-server-core.h"); @cInclude("wayland-server-core.h");
//@cInclude("wlr/backend.h"); //@cInclude("wlr/backend.h");
//@cInclude("wlr/render/wlr_renderer.h"); //@cInclude("wlr/render/wlr_renderer.h");

View File

@ -17,6 +17,8 @@
const std = @import("std"); const std = @import("std");
const c = @import("../c.zig");
const Error = @import("../command.zig").Error; const Error = @import("../command.zig").Error;
const Seat = @import("../Seat.zig"); const Seat = @import("../Seat.zig");
@ -31,17 +33,31 @@ pub fn spawn(
const cmd = try std.mem.join(allocator, " ", args[1..]); const cmd = try std.mem.join(allocator, " ", args[1..]);
defer allocator.free(cmd); 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_args = [_:null]?[*:0]const u8{ "/bin/sh", "-c", cmdZ, null };
const child = try std.ChildProcess.init(&child_args, allocator);
defer child.deinit();
std.ChildProcess.spawn(child) catch |err| { const pid = std.os.fork() catch {
out.* = try std.fmt.allocPrint( out.* = try std.fmt.allocPrint(allocator, "fork/execve failed", .{});
allocator,
"failed to spawn {}: {}.",
.{ cmd, err },
);
return Error.Other; 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;
}
} }