diff --git a/changelog.md b/changelog.md index fa1b90d..c1bf64d 100644 --- a/changelog.md +++ b/changelog.md @@ -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. diff --git a/src/auth.zig b/src/auth.zig index 27bd145..07fa1fa 100644 --- a/src/auth.zig +++ b/src/auth.zig @@ -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); } } diff --git a/src/config/Config.zig b/src/config/Config.zig index 84230d8..8b21dee 100644 --- a/src/config/Config.zig +++ b/src/config/Config.zig @@ -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, diff --git a/src/config/Lang.zig b/src/config/Lang.zig index a677e54..9f199c0 100644 --- a/src/config/Lang.zig +++ b/src/config/Lang.zig @@ -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", diff --git a/src/interop.zig b/src/interop.zig index d2c0a8e..c193c7d 100644 --- a/src/interop.zig +++ b/src/interop.zig @@ -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; diff --git a/src/main.zig b/src/main.zig index b82f1c0..07bd6e8 100644 --- a/src/main.zig +++ b/src/main.zig @@ -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| {