mirror of
https://github.com/Dasharo/systemd.git
synced 2026-03-06 15:02:31 -08:00
ptyforward: rework PTY forwarder logic used by nspawn to utilize the normal event loop
We really should not run manual event loops anymore, but standardize on sd_event, so that we can run sd_bus connections from it eventually.
This commit is contained in:
@@ -44,6 +44,7 @@
|
||||
#include "cgroup-show.h"
|
||||
#include "cgroup-util.h"
|
||||
#include "ptyfwd.h"
|
||||
#include "event-util.h"
|
||||
|
||||
static char **arg_property = NULL;
|
||||
static bool arg_all = false;
|
||||
@@ -662,12 +663,14 @@ static int login_machine(sd_bus *bus, char **args, unsigned n) {
|
||||
_cleanup_bus_message_unref_ sd_bus_message *reply = NULL, *reply2 = NULL, *reply3 = NULL;
|
||||
_cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
|
||||
_cleanup_bus_close_unref_ sd_bus *container_bus = NULL;
|
||||
_cleanup_(pty_forward_freep) PTYForward *forward = NULL;
|
||||
_cleanup_event_unref_ sd_event *event = NULL;
|
||||
_cleanup_close_ int master = -1;
|
||||
_cleanup_free_ char *getty = NULL;
|
||||
const char *path, *pty, *p;
|
||||
uint32_t leader;
|
||||
sigset_t mask;
|
||||
int r;
|
||||
int r, ret = 0;
|
||||
|
||||
assert(bus);
|
||||
assert(args);
|
||||
@@ -677,6 +680,18 @@ static int login_machine(sd_bus *bus, char **args, unsigned n) {
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
r = sd_event_default(&event);
|
||||
if (r < 0) {
|
||||
log_error("Failed to get event loop: %s", strerror(-r));
|
||||
return r;
|
||||
}
|
||||
|
||||
r = sd_bus_attach_event(bus, event, 0);
|
||||
if (r < 0) {
|
||||
log_error("Failed to attach bus to event loop: %s", strerror(-r));
|
||||
return r;
|
||||
}
|
||||
|
||||
r = sd_bus_call_method(
|
||||
bus,
|
||||
"org.freedesktop.machine1",
|
||||
@@ -766,17 +781,29 @@ static int login_machine(sd_bus *bus, char **args, unsigned n) {
|
||||
|
||||
log_info("Connected to container %s. Press ^] three times within 1s to exit session.", args[1]);
|
||||
|
||||
r = process_pty(master, &mask, 0, 0);
|
||||
sd_event_add_signal(event, NULL, SIGINT, NULL, NULL);
|
||||
sd_event_add_signal(event, NULL, SIGTERM, NULL, NULL);
|
||||
|
||||
r = pty_forward_new(event, master, &forward);
|
||||
if (r < 0) {
|
||||
log_error("Failed to process pseudo tty: %s", strerror(-r));
|
||||
log_error("Failed to create PTY forwarder: %s", strerror(-r));
|
||||
return r;
|
||||
}
|
||||
|
||||
r = sd_event_loop(event);
|
||||
if (r < 0) {
|
||||
log_error("Failed to run event loop: %s", strerror(-r));
|
||||
return r;
|
||||
}
|
||||
|
||||
forward = pty_forward_free(forward);
|
||||
|
||||
fputc('\n', stdout);
|
||||
|
||||
log_info("Connection to container %s terminated.", args[1]);
|
||||
|
||||
return 0;
|
||||
sd_event_get_exit_code(event, &ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void help(void) {
|
||||
|
||||
@@ -89,6 +89,7 @@
|
||||
#include "copy.h"
|
||||
#include "base-filesystem.h"
|
||||
#include "barrier.h"
|
||||
#include "event-util.h"
|
||||
|
||||
#ifdef HAVE_SECCOMP
|
||||
#include "seccomp-util.h"
|
||||
@@ -2972,6 +2973,22 @@ static int wait_for_container(pid_t pid, ContainerStatus *container) {
|
||||
|
||||
static void nop_handler(int sig) {}
|
||||
|
||||
static int on_orderly_shutdown(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata) {
|
||||
pid_t pid;
|
||||
|
||||
pid = PTR_TO_UINT32(userdata);
|
||||
if (pid > 0) {
|
||||
if (kill(pid, SIGRTMIN+3) >= 0) {
|
||||
log_info("Trying to halt container. Send SIGTERM again to trigger immediate termination.");
|
||||
sd_event_source_set_userdata(s, NULL);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
sd_event_exit(sd_event_source_get_event(s), 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
|
||||
_cleanup_free_ char *kdbus_domain = NULL, *device_path = NULL, *root_device = NULL, *home_device = NULL, *srv_device = NULL;
|
||||
@@ -3153,11 +3170,12 @@ int main(int argc, char *argv[]) {
|
||||
"STATUS=Container running.");
|
||||
|
||||
assert_se(sigemptyset(&mask) == 0);
|
||||
assert_se(sigemptyset(&mask_chld) == 0);
|
||||
sigaddset(&mask_chld, SIGCHLD);
|
||||
sigset_add_many(&mask, SIGCHLD, SIGWINCH, SIGTERM, SIGINT, -1);
|
||||
assert_se(sigprocmask(SIG_BLOCK, &mask, NULL) == 0);
|
||||
|
||||
assert_se(sigemptyset(&mask_chld) == 0);
|
||||
assert_se(sigaddset(&mask_chld, SIGCHLD) == 0);
|
||||
|
||||
for (;;) {
|
||||
ContainerStatus container_status;
|
||||
_cleanup_(barrier_destroy) Barrier barrier = BARRIER_NULL;
|
||||
@@ -3494,6 +3512,8 @@ int main(int argc, char *argv[]) {
|
||||
|
||||
/* wait for child-setup to be done */
|
||||
if (barrier_place_and_sync(&barrier)) {
|
||||
_cleanup_event_unref_ sd_event *event = NULL;
|
||||
_cleanup_(pty_forward_freep) PTYForward *forward = NULL;
|
||||
int ifi = 0;
|
||||
|
||||
r = move_network_interfaces(pid);
|
||||
@@ -3532,12 +3552,39 @@ int main(int argc, char *argv[]) {
|
||||
* control to the code to run inside the container. */
|
||||
barrier_place(&barrier);
|
||||
|
||||
k = process_pty(master, &mask, arg_boot ? pid : 0, SIGRTMIN+3);
|
||||
if (k < 0) {
|
||||
r = EXIT_FAILURE;
|
||||
break;
|
||||
r = sd_event_new(&event);
|
||||
if (r < 0) {
|
||||
log_error("Failed to get default event source: %s", strerror(-r));
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if (arg_boot) {
|
||||
/* Try to kill the init system on SIGINT or SIGTERM */
|
||||
sd_event_add_signal(event, NULL, SIGINT, on_orderly_shutdown, UINT32_TO_PTR(pid));
|
||||
sd_event_add_signal(event, NULL, SIGTERM, on_orderly_shutdown, UINT32_TO_PTR(pid));
|
||||
} else {
|
||||
/* Immediately exit */
|
||||
sd_event_add_signal(event, NULL, SIGINT, NULL, NULL);
|
||||
sd_event_add_signal(event, NULL, SIGTERM, NULL, NULL);
|
||||
}
|
||||
|
||||
/* simply exit on sigchld */
|
||||
sd_event_add_signal(event, NULL, SIGCHLD, NULL, NULL);
|
||||
|
||||
r = pty_forward_new(event, master, &forward);
|
||||
if (r < 0) {
|
||||
log_error("Failed to create PTY forwarder: %s", strerror(-r));
|
||||
goto finish;
|
||||
}
|
||||
|
||||
r = sd_event_loop(event);
|
||||
if (r < 0) {
|
||||
log_error("Failed to run event loop: %s", strerror(-r));
|
||||
return r;
|
||||
}
|
||||
|
||||
forward = pty_forward_free(forward);
|
||||
|
||||
if (!arg_quiet)
|
||||
putc('\n', stdout);
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -24,4 +24,11 @@
|
||||
#include <sys/types.h>
|
||||
#include <signal.h>
|
||||
|
||||
int process_pty(int master, sigset_t *mask, pid_t kill_pid, int signo);
|
||||
#include "sd-event.h"
|
||||
|
||||
typedef struct PTYForward PTYForward;
|
||||
|
||||
int pty_forward_new(sd_event *event, int master, PTYForward **f);
|
||||
PTYForward *pty_forward_free(PTYForward *f);
|
||||
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(PTYForward*, pty_forward_free);
|
||||
|
||||
Reference in New Issue
Block a user