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) {
|
if (pid == 0) {
|
||||||
// Clean things up for the child in an intermediate fork
|
util.post_fork_pre_execve();
|
||||||
if (c.setsid() < 0) unreachable;
|
|
||||||
if (os.system.sigprocmask(os.SIG.SETMASK, &os.empty_sigset, null) < 0) unreachable;
|
|
||||||
|
|
||||||
const pid2 = os.fork() catch c._exit(1);
|
const pid2 = os.fork() catch c._exit(1);
|
||||||
if (pid2 == 0) os.execveZ("/bin/sh", &child_args, std.c.environ) 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;
|
pub var server: Server = undefined;
|
||||||
|
|
||||||
fn sa_handler(_: c_int) callconv(.C) void {}
|
|
||||||
|
|
||||||
pub fn main() anyerror!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
|
// This line is here because of https://github.com/ziglang/zig/issues/7807
|
||||||
const argv: [][*:0]const u8 = os.argv;
|
const argv: [][*:0]const u8 = os.argv;
|
||||||
const result = flags.parse(argv[1..], &[_]flags.Flag{
|
const result = flags.parse(argv[1..], &[_]flags.Flag{
|
||||||
@ -107,6 +96,16 @@ pub fn main() anyerror!void {
|
|||||||
.warn, .err => .err,
|
.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", .{});
|
std.log.info("initializing server", .{});
|
||||||
try server.init();
|
try server.init();
|
||||||
defer server.deinit();
|
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 child_args = [_:null]?[*:0]const u8{ "/bin/sh", "-c", cmd, null };
|
||||||
const pid = try os.fork();
|
const pid = try os.fork();
|
||||||
if (pid == 0) {
|
if (pid == 0) {
|
||||||
if (c.setsid() < 0) unreachable;
|
util.post_fork_pre_execve();
|
||||||
if (os.system.sigprocmask(os.SIG.SETMASK, &os.empty_sigset, null) < 0) unreachable;
|
|
||||||
os.execveZ("/bin/sh", &child_args, std.c.environ) catch c._exit(1);
|
os.execveZ("/bin/sh", &child_args, std.c.environ) catch c._exit(1);
|
||||||
}
|
}
|
||||||
util.gpa.free(cmd);
|
util.gpa.free(cmd);
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
// This file is part of river, a dynamic tiling wayland compositor.
|
// 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
|
// 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
|
// 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/>.
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
const os = std.os;
|
||||||
|
|
||||||
|
const c = @import("c.zig");
|
||||||
|
|
||||||
/// The global general-purpose allocator used throughout river's code
|
/// The global general-purpose allocator used throughout river's code
|
||||||
pub const gpa = std.heap.c_allocator;
|
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