Run daemons in their own session.

This commit is contained in:
Jonas 'Sortie' Termansen 2024-06-16 19:42:13 +00:00
parent 6e51c1ae51
commit e90e2077e7
1 changed files with 14 additions and 31 deletions

View File

@ -313,6 +313,7 @@ struct communication
static pid_t main_pid; static pid_t main_pid;
static pid_t forward_signal_pid = -1; static pid_t forward_signal_pid = -1;
static int tty_fd;
static volatile sig_atomic_t caught_exit_signal = -1; static volatile sig_atomic_t caught_exit_signal = -1;
static sigset_t handled_signals; static sigset_t handled_signals;
@ -2545,31 +2546,24 @@ static void daemon_start(struct daemon* daemon)
fatal("fork: %m"); fatal("fork: %m");
if ( daemon->need_tty ) if ( daemon->need_tty )
{ {
if ( tcgetattr(0, &daemon->oldtio) ) if ( tcgetattr(tty_fd, &daemon->oldtio) )
fatal("tcgetattr: %m"); fatal("tcgetattr: %m");
} }
if ( daemon->pid == 0 ) if ( daemon->pid == 0 )
{ {
uninstall_signal_handler(); uninstall_signal_handler();
close(errfds[0]); close(errfds[0]);
if ( setsid() < 0 )
exit_errfd(errfds[1], "setsid");
if ( chdir(cd) < 0 ) if ( chdir(cd) < 0 )
exit_errfd(errfds[1], "chdir"); exit_errfd(errfds[1], "chdir");
if ( daemon->need_tty ) if ( daemon->need_tty )
{ {
pid_t pid = getpid(); if ( ioctl(tty_fd, TIOCSCTTY, 1) < 0 )
// TODO: Support for setsid(2). exit_errfd(errfds[1], "TIOCSCTTY");
if ( setpgid(0, 0) < 0 )
exit_errfd(errfds[1], "setpgid");
sigset_t oldset, sigttou;
sigemptyset(&sigttou);
sigaddset(&sigttou, SIGTTOU);
sigprocmask(SIG_BLOCK, &sigttou, &oldset);
if ( tcsetpgrp(0, pid) < 0 )
exit_errfd(errfds[1], "tcsetpgrp");
daemon->oldtio.c_cflag |= CREAD; daemon->oldtio.c_cflag |= CREAD;
if ( tcsetattr(0, TCSANOW, &daemon->oldtio) < 0 ) if ( tcsetattr(tty_fd, TCSANOW, &daemon->oldtio) < 0 )
exit_errfd(errfds[1], "tcsetattr"); exit_errfd(errfds[1], "tcsetattr");
sigprocmask(SIG_SETMASK, &oldset, NULL);
dup3(errfds[1], 3, O_CLOEXEC); dup3(errfds[1], 3, O_CLOEXEC);
closefrom(4); closefrom(4);
} }
@ -2723,10 +2717,10 @@ static void daemon_on_exit(struct daemon* daemon, int exit_code)
sigemptyset(&sigttou); sigemptyset(&sigttou);
sigaddset(&sigttou, SIGTTOU); sigaddset(&sigttou, SIGTTOU);
sigprocmask(SIG_BLOCK, &sigttou, &oldset); sigprocmask(SIG_BLOCK, &sigttou, &oldset);
if ( tcsetattr(0, TCSAFLUSH, &daemon->oldtio) ) if ( tcsetattr(tty_fd, TCSAFLUSH, &daemon->oldtio) )
fatal("tcsetattr: %m"); fatal("tcsetattr: %m");
if ( tcsetpgrp(0, getpgid(0)) < 0 ) if ( ioctl(tty_fd, TIOCSCTTY, 1) < 0 )
fatal("tcsetpgrp: %m"); fatal("TIOCSCTTY: %m");
sigprocmask(SIG_SETMASK, &oldset, NULL); sigprocmask(SIG_SETMASK, &oldset, NULL);
} }
daemon_on_finished(daemon); daemon_on_finished(daemon);
@ -3728,12 +3722,8 @@ static void set_hostname(void)
static void set_kblayout(void) static void set_kblayout(void)
{ {
int tty_fd = open("/dev/tty", O_RDWR);
if ( !tty_fd )
return warning("unable to set keyboard layout: /dev/tty: %m");
bool unsupported = tcgetblob(tty_fd, "kblayout", NULL, 0) < 0 && bool unsupported = tcgetblob(tty_fd, "kblayout", NULL, 0) < 0 &&
(errno == ENOTTY || errno == ENOENT); (errno == ENOTTY || errno == ENOENT);
close(tty_fd);
if ( unsupported ) if ( unsupported )
return; return;
FILE* fp = fopen("/etc/kblayout", "r"); FILE* fp = fopen("/etc/kblayout", "r");
@ -3766,9 +3756,6 @@ static void set_kblayout(void)
static void set_videomode(void) static void set_videomode(void)
{ {
int tty_fd = open("/dev/tty", O_RDWR);
if ( !tty_fd )
return warning("unable to set video mode: /dev/tty: %m");
struct tiocgdisplay display; struct tiocgdisplay display;
struct tiocgdisplays gdisplays; struct tiocgdisplays gdisplays;
memset(&gdisplays, 0, sizeof(gdisplays)); memset(&gdisplays, 0, sizeof(gdisplays));
@ -3776,7 +3763,6 @@ static void set_videomode(void)
gdisplays.displays = &display; gdisplays.displays = &display;
bool unsupported = ioctl(tty_fd, TIOCGDISPLAYS, &gdisplays) < 0 || bool unsupported = ioctl(tty_fd, TIOCGDISPLAYS, &gdisplays) < 0 ||
gdisplays.count == 0; gdisplays.count == 0;
close(tty_fd);
if ( unsupported ) if ( unsupported )
return; return;
FILE* fp = fopen("/etc/videomode", "r"); FILE* fp = fopen("/etc/videomode", "r");
@ -4303,13 +4289,14 @@ int main(int argc, char* argv[])
if ( getinit(0) != getpid() ) if ( getinit(0) != getpid() )
fatal("System is already managed by an init process"); fatal("System is already managed by an init process");
if ( !isatty(0) || !isatty(1) || !isatty(2) )
fatal("stdin, stdout, and stderr must be the terminal");
// Register handler that shuts down the system when init exits. // Register handler that shuts down the system when init exits.
if ( atexit(niht) != 0 ) if ( atexit(niht) != 0 )
fatal("atexit: %m"); fatal("atexit: %m");
// Remember the controlling terminal to give it away and reclaim it.
if ( (tty_fd = open("/dev/tty", O_RDWR | O_CLOEXEC)) < 0 )
fatal("/dev/tty: %m");
// Handle signals but block them until the safe points where we handle them. // Handle signals but block them until the safe points where we handle them.
// All child processes have to uninstall the signal handler and unblock the // All child processes have to uninstall the signal handler and unblock the
// signals or they keep blocking the signals. // signals or they keep blocking the signals.
@ -4461,9 +4448,6 @@ int main(int argc, char* argv[])
chain_location_dev_made = true; chain_location_dev_made = true;
close(new_dev_fd); close(new_dev_fd);
close(old_dev_fd); close(old_dev_fd);
int tty_fd = open("/dev/tty", O_RDWR | O_CLOEXEC);
if ( tty_fd < 0 )
fatal("/dev/tty: %m");
// TODO: Forward the early init log to the chain init. // TODO: Forward the early init log to the chain init.
// Run the chain booted operating system. // Run the chain booted operating system.
pid_t child_pid = fork(); pid_t child_pid = fork();
@ -4512,7 +4496,6 @@ int main(int argc, char* argv[])
forward_signal_pid = -1; // Racy with waitpid. forward_signal_pid = -1; // Racy with waitpid.
if ( ioctl(tty_fd, TIOCSCTTY, 1) < 0 ) if ( ioctl(tty_fd, TIOCSCTTY, 1) < 0 )
fatal("ioctl: TIOCSCTTY: %m"); fatal("ioctl: TIOCSCTTY: %m");
close(tty_fd);
if ( WIFEXITED(status) ) if ( WIFEXITED(status) )
return WEXITSTATUS(status); return WEXITSTATUS(status);
else if ( WIFSIGNALED(status) ) else if ( WIFSIGNALED(status) )