river: fix SIGPIPE handling, cleanup fork/execve
Installing an empty handler does not have the same effect as using SIG_IGN as the failing write syscall will not return EPIPE.
This commit is contained in:
parent
600fd2e73c
commit
1a9cba2aa9
@ -40,10 +40,7 @@ pub fn spawn(
|
||||
};
|
||||
|
||||
if (pid == 0) {
|
||||
// Clean things up for the child in an intermediate fork
|
||||
if (c.setsid() < 0) unreachable;
|
||||
if (os.system.sigprocmask(os.SIG.SETMASK, &os.empty_sigset, null) < 0) unreachable;
|
||||
|
||||
util.post_fork_pre_execve();
|
||||
const pid2 = os.fork() catch c._exit(1);
|
||||
if (pid2 == 0) os.execveZ("/bin/sh", &child_args, std.c.environ) catch c._exit(1);
|
||||
|
||||
|
@ -41,18 +41,7 @@ const usage: []const u8 =
|
||||
|
||||
pub var server: Server = undefined;
|
||||
|
||||
fn sa_handler(_: c_int) callconv(.C) void {}
|
||||
|
||||
pub fn main() anyerror!void {
|
||||
// ignore SIGPIPE so we don't get killed when socket unexpectedly closes (thanks xwayland)
|
||||
// use our own handler instead of SIG_IGN so we don't leak this when execve()
|
||||
const act = os.Sigaction{
|
||||
.handler = .{ .handler = sa_handler },
|
||||
.mask = os.empty_sigset,
|
||||
.flags = 0,
|
||||
};
|
||||
os.sigaction(os.SIG.PIPE, &act, null);
|
||||
|
||||
// This line is here because of https://github.com/ziglang/zig/issues/7807
|
||||
const argv: [][*:0]const u8 = os.argv;
|
||||
const result = flags.parse(argv[1..], &[_]flags.Flag{
|
||||
@ -107,6 +96,16 @@ pub fn main() anyerror!void {
|
||||
.warn, .err => .err,
|
||||
});
|
||||
|
||||
// Ignore SIGPIPE so we don't get killed when writing to a socket that
|
||||
// has had its read end closed by another process.
|
||||
const sig_ign = os.Sigaction{
|
||||
// TODO(zig): Remove this casting after https://github.com/ziglang/zig/pull/12410
|
||||
.handler = .{ .handler = @intToPtr(os.Sigaction.handler_fn, @ptrToInt(os.SIG.IGN)) },
|
||||
.mask = os.empty_sigset,
|
||||
.flags = 0,
|
||||
};
|
||||
os.sigaction(os.SIG.PIPE, &sig_ign, null);
|
||||
|
||||
std.log.info("initializing server", .{});
|
||||
try server.init();
|
||||
defer server.deinit();
|
||||
@ -120,8 +119,7 @@ pub fn main() anyerror!void {
|
||||
const child_args = [_:null]?[*:0]const u8{ "/bin/sh", "-c", cmd, null };
|
||||
const pid = try os.fork();
|
||||
if (pid == 0) {
|
||||
if (c.setsid() < 0) unreachable;
|
||||
if (os.system.sigprocmask(os.SIG.SETMASK, &os.empty_sigset, null) < 0) unreachable;
|
||||
util.post_fork_pre_execve();
|
||||
os.execveZ("/bin/sh", &child_args, std.c.environ) catch c._exit(1);
|
||||
}
|
||||
util.gpa.free(cmd);
|
||||
|
@ -1,6 +1,6 @@
|
||||
// This file is part of river, a dynamic tiling wayland compositor.
|
||||
//
|
||||
// Copyright 2020 The River Developers
|
||||
// Copyright 2022 The River Developers
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
@ -15,6 +15,21 @@
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
const std = @import("std");
|
||||
const os = std.os;
|
||||
|
||||
const c = @import("c.zig");
|
||||
|
||||
/// The global general-purpose allocator used throughout river's code
|
||||
pub const gpa = std.heap.c_allocator;
|
||||
|
||||
pub fn post_fork_pre_execve() void {
|
||||
if (c.setsid() < 0) unreachable;
|
||||
if (os.system.sigprocmask(os.SIG.SETMASK, &os.empty_sigset, null) < 0) unreachable;
|
||||
const sig_dfl = os.Sigaction{
|
||||
// TODO(zig): Remove this casting after https://github.com/ziglang/zig/pull/12410
|
||||
.handler = .{ .handler = @intToPtr(?os.Sigaction.handler_fn, @ptrToInt(os.SIG.DFL)) },
|
||||
.mask = os.empty_sigset,
|
||||
.flags = 0,
|
||||
};
|
||||
os.sigaction(os.SIG.PIPE, &sig_dfl, null);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user