Clean up when SIGTERM is received (#597)

* clean up child processes on SIGTERM

* small code improvement

* consistency.. i guess?
pull/603/head
アシュ 1 month ago committed by GitHub
parent 365933e39e
commit 7c71dee3db
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -42,4 +42,4 @@ session_index = 0
+ X Server PID is fetched from /tmp/X{d}.lock to be able to kill the process since it detaches.
+ Non .desktop files are now ignored in sessions directory.
+ PAM auth is now done in a child process. (Fixes some issues with logging out and back in).
+ When ly receives SIGTERM, the terminal is now cleared.
+ When ly receives SIGTERM, the terminal is now cleared and existing child processes are cleaned up.

@ -10,6 +10,16 @@ const utmp = interop.utmp;
const Utmp = utmp.utmp;
const SharedError = @import("SharedError.zig");
var xorg_pid: std.os.pid_t = 0;
pub fn xorgSignalHandler(i: c_int) callconv(.C) void {
if (xorg_pid > 0) _ = std.c.kill(xorg_pid, i);
}
var child_pid: std.os.pid_t = 0;
pub fn sessionSignalHandler(i: c_int) callconv(.C) void {
if (child_pid > 0) _ = std.c.kill(child_pid, i);
}
pub fn authenticate(allocator: Allocator, config: Config, desktop: Desktop, login: Text, password: *Text) !void {
var tty_buffer: [2]u8 = undefined;
const tty_str = try std.fmt.bufPrintZ(&tty_buffer, "{d}", .{config.tty});
@ -86,8 +96,8 @@ pub fn authenticate(allocator: Allocator, config: Config, desktop: Desktop, logi
var shared_err = try SharedError.init();
defer shared_err.deinit();
const pid = try std.os.fork();
if (pid == 0) {
child_pid = try std.os.fork();
if (child_pid == 0) {
// Set the user information
status = interop.initgroups(pwd.pw_name, pwd.pw_gid);
if (status != 0) {
@ -159,10 +169,18 @@ pub fn authenticate(allocator: Allocator, config: Config, desktop: Desktop, logi
}
var entry: Utmp = std.mem.zeroes(Utmp);
addUtmpEntry(&entry, pwd.pw_name, pid) catch {};
addUtmpEntry(&entry, pwd.pw_name, child_pid) catch {};
// If we receive SIGTERM, forward it to child_pid
const act = std.os.Sigaction{
.handler = .{ .handler = &sessionSignalHandler },
.mask = std.os.empty_sigset,
.flags = 0,
};
try std.os.sigaction(std.os.SIG.TERM, &act, null);
// Wait for the session to stop
_ = std.os.waitpid(pid, 0);
_ = std.os.waitpid(child_pid, 0);
removeUtmpEntry(&entry);
@ -400,20 +418,21 @@ fn executeX11Cmd(shell: [*:0]const u8, pw_dir: [*:0]const u8, config: Config, de
std.os.exit(0);
}
var status: c_int = 0;
var ok: c_int = undefined;
var xcb: ?*interop.xcb.xcb_connection_t = null;
while (ok != 0) {
xcb = interop.xcb.xcb_connect(null, null);
ok = interop.xcb.xcb_connection_has_error(xcb);
_ = std.c.kill(pid, 0);
if (std.c._errno().* == interop.ESRCH and ok != 0) return;
status = std.c.kill(pid, 0);
if (std.os.errno(status) == .SRCH and ok != 0) return;
}
// X Server detaches from the process.
// PID can be fetched from /tmp/X{d}.lock
const x_pid = try getXPid(display_num);
const xorg_pid = try std.os.fork();
xorg_pid = try std.os.fork();
if (xorg_pid == 0) {
var cmd_buffer: [1024]u8 = undefined;
const cmd_str = std.fmt.bufPrintZ(&cmd_buffer, "{s} {s}", .{ config.x_cmd_setup, desktop_cmd }) catch std.os.exit(1);
@ -421,13 +440,20 @@ fn executeX11Cmd(shell: [*:0]const u8, pw_dir: [*:0]const u8, config: Config, de
std.os.exit(0);
}
var status: c_int = 0;
// If we receive SIGTERM, clean up by killing the xorg_pid process
const act = std.os.Sigaction{
.handler = .{ .handler = &xorgSignalHandler },
.mask = std.os.empty_sigset,
.flags = 0,
};
try std.os.sigaction(std.os.SIG.TERM, &act, null);
_ = std.os.waitpid(xorg_pid, 0);
interop.xcb.xcb_disconnect(xcb);
_ = std.c.kill(x_pid, 0);
if (std.c._errno().* != interop.ESRCH) {
_ = std.c.kill(x_pid, interop.SIGTERM);
status = std.c.kill(x_pid, 0);
if (std.os.errno(status) != .SRCH) {
_ = std.c.kill(x_pid, std.os.SIG.TERM);
_ = std.c.waitpid(x_pid, &status, 0);
}
}

@ -4,8 +4,6 @@ const enums = @import("../enums.zig");
const Animation = enums.Animation;
const Input = enums.Input;
const Config = @This();
animation: Animation = .none,
asterisk: u8 = '*',
bg: u8 = 0,

@ -1,5 +1,3 @@
const Lang = @This();
capslock: []const u8 = "capslock",
err_alloc: []const u8 = "failed memory allocation",
err_bounds: []const u8 = "out-of-bounds index",

@ -44,9 +44,6 @@ pub const passwd = extern struct {
pw_shell: [*:0]u8,
};
pub const SIGTERM: c_int = 15;
pub const ESRCH: c_int = 3;
pub const _POSIX_HOST_NAME_MAX: c_int = 0xFF;
pub const _SC_HOST_NAME_MAX: c_int = 0xB4;

@ -23,7 +23,17 @@ const utils = @import("tui/utils.zig");
const Ini = ini.Ini;
const termbox = interop.termbox;
var session_pid: std.os.pid_t = -1;
pub fn signalHandler(i: c_int) callconv(.C) void {
if (session_pid == 0) return;
// Forward signal to session to clean up
if (session_pid > 0) {
_ = std.c.kill(session_pid, i);
var status: c_int = 0;
_ = std.c.waitpid(session_pid, &status, 0);
}
termbox.tb_shutdown();
std.c.exit(i);
}
@ -532,7 +542,7 @@ pub fn main() !void {
var shared_err = try SharedError.init();
defer shared_err.deinit();
const session_pid = try std.os.fork();
session_pid = try std.os.fork();
if (session_pid == 0) {
auth.authenticate(allocator, config, desktop, login, &password) catch |err| {
shared_err.writeError(err);
@ -542,6 +552,7 @@ pub fn main() !void {
}
_ = std.os.waitpid(session_pid, 0);
session_pid = -1;
var auth_err = shared_err.readError();
if (auth_err) |err| {

Loading…
Cancel
Save