From: Lennart Poettering Date: Fri, 31 Jan 2025 16:40:46 +0000 (+0100) Subject: core: also issue OSC 3008 from service context X-Git-Tag: v258-rc1~1227^2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=refs%2Fpull%2F35224%2Fhead;p=thirdparty%2Fsystemd.git core: also issue OSC 3008 from service context (Note: we also change TEST-13-NSPAWN.machined.sh minimally here, because it checks for byte precise output of a pty allocated for a service invocation - which it's not going to get if it claims that the pty is an all-powerful one. After all this PR ensures that we'll generate the new OSC sequence on non-dumb terminals associated with services. Hence, set TERM=dumb explicitly to ensure no ANSI sequences are generated, ever. Which is a nice test btw that TERM=dumb really does its thing here.) --- diff --git a/src/core/exec-invoke.c b/src/core/exec-invoke.c index 490b3a522ae..94157a9e99e 100644 --- a/src/core/exec-invoke.c +++ b/src/core/exec-invoke.c @@ -46,6 +46,7 @@ #include "missing_securebits.h" #include "missing_syscall.h" #include "mkdir-label.h" +#include "osc-context.h" #include "proc-cmdline.h" #include "process-util.h" #include "psi-util.h" @@ -4386,6 +4387,9 @@ static void prepare_terminal( } (void) exec_context_apply_tty_size(context, STDIN_FILENO, STDOUT_FILENO, /* tty_path= */ NULL); + + if (use_ansi) + (void) osc_context_open_service(p->unit_id, p->invocation_id, /* ret_seq= */ NULL); } int exec_invoke( @@ -4562,8 +4566,10 @@ int exec_invoke( * disallocate the VT), to get rid of any prior uses of the device. Note that we do not keep any fd * open here, hence some of the settings made here might vanish again, depending on the TTY driver * used. A 2nd ("constructive") initialization after we opened the input/output fds we actually want - * will fix this. */ - exec_context_tty_reset(context, params); + * will fix this. Note that we pass a NULL invocation ID here – as exec_context_tty_reset() expects + * the invocation ID associated with the OSC 3008 context ID to close. But we don't want to close any + * OSC 3008 context here, and opening a fresh OSC 3008 context happens a bit further down. */ + exec_context_tty_reset(context, params, /* invocation_id= */ SD_ID128_NULL); if (params->shall_confirm_spawn && exec_context_shall_confirm_spawn(context)) { _cleanup_free_ char *cmdline = NULL; diff --git a/src/core/execute.c b/src/core/execute.c index 7d99e723288..a7e8b3340c0 100644 --- a/src/core/execute.c +++ b/src/core/execute.c @@ -39,6 +39,7 @@ #include "format-util.h" #include "glob-util.h" #include "hexdecoct.h" +#include "io-util.h" #include "ioprio-util.h" #include "lock-util.h" #include "log.h" @@ -50,6 +51,7 @@ #include "missing_prctl.h" #include "mkdir-label.h" #include "namespace.h" +#include "osc-context.h" #include "parse-util.h" #include "path-util.h" #include "process-util.h" @@ -144,7 +146,7 @@ int exec_context_apply_tty_size( return terminal_set_size_fd(output_fd, tty_path, rows, cols); } -void exec_context_tty_reset(const ExecContext *context, const ExecParameters *p) { +void exec_context_tty_reset(const ExecContext *context, const ExecParameters *p, sd_id128_t invocation_id) { _cleanup_close_ int _fd = -EBADF, lock_fd = -EBADF; int fd, r; @@ -188,6 +190,23 @@ void exec_context_tty_reset(const ExecContext *context, const ExecParameters *p) if (r < 0) log_debug_errno(r, "Failed to configure TTY dimensions, ignoring: %m"); + if (!sd_id128_is_null(invocation_id)) { + sd_id128_t context_id; + + r = osc_context_id_from_invocation_id(invocation_id, &context_id); + if (r < 0) + log_debug_errno(r, "Failed to derive context ID from invocation ID, ignoring: %m"); + else { + _cleanup_free_ char *seq = NULL; + + r = osc_context_close(context_id, &seq); + if (r < 0) + log_debug_errno(r, "Failed to acquire OSC close sequence, ignoring: %m"); + else + (void) loop_write(fd, seq, SIZE_MAX); + } + } + if (context->tty_vhangup) (void) terminal_vhangup_fd(fd); @@ -1630,7 +1649,7 @@ void exec_context_free_log_extra_fields(ExecContext *c) { c->n_log_extra_fields = 0; } -void exec_context_revert_tty(ExecContext *c) { +void exec_context_revert_tty(ExecContext *c, sd_id128_t invocation_id) { _cleanup_close_ int fd = -EBADF; const char *path; struct stat st; @@ -1639,7 +1658,7 @@ void exec_context_revert_tty(ExecContext *c) { assert(c); /* First, reset the TTY (possibly kicking everybody else from the TTY) */ - exec_context_tty_reset(c, /* parameters= */ NULL); + exec_context_tty_reset(c, /* parameters= */ NULL, invocation_id); /* And then undo what chown_terminal() did earlier. Note that we only do this if we have a path * configured. If the TTY was passed to us as file descriptor we assume the TTY is opened and managed diff --git a/src/core/execute.h b/src/core/execute.h index abfa31afcb6..8128c4c9286 100644 --- a/src/core/execute.h +++ b/src/core/execute.h @@ -538,14 +538,14 @@ bool exec_context_get_effective_bind_log_sockets(const ExecContext *c); void exec_context_free_log_extra_fields(ExecContext *c); -void exec_context_revert_tty(ExecContext *c); +void exec_context_revert_tty(ExecContext *c, sd_id128_t invocation_id); int exec_context_get_clean_directories(ExecContext *c, char **prefix, ExecCleanMask mask, char ***ret); int exec_context_get_clean_mask(ExecContext *c, ExecCleanMask *ret); const char* exec_context_tty_path(const ExecContext *context); int exec_context_apply_tty_size(const ExecContext *context, int input_fd, int output_fd, const char *tty_path); -void exec_context_tty_reset(const ExecContext *context, const ExecParameters *p); +void exec_context_tty_reset(const ExecContext *context, const ExecParameters *p, sd_id128_t invocation_id); uint64_t exec_context_get_rlimit(const ExecContext *c, const char *name); int exec_context_get_oom_score_adjust(const ExecContext *c); diff --git a/src/core/service.c b/src/core/service.c index 112e4370a5a..12b367ccc83 100644 --- a/src/core/service.c +++ b/src/core/service.c @@ -2178,7 +2178,7 @@ static void service_enter_dead(Service *s, ServiceResult f, bool allow_restart) (void) unlink(s->pid_file); /* Reset TTY ownership if necessary */ - exec_context_revert_tty(&s->exec_context); + exec_context_revert_tty(&s->exec_context, UNIT(s)->invocation_id); } static void service_enter_stop_post(Service *s, ServiceResult f) { diff --git a/test/units/TEST-13-NSPAWN.machined.sh b/test/units/TEST-13-NSPAWN.machined.sh index 4875e48f809..d8c15dfcfb8 100755 --- a/test/units/TEST-13-NSPAWN.machined.sh +++ b/test/units/TEST-13-NSPAWN.machined.sh @@ -399,7 +399,7 @@ grep -q "BAR" /tmp/none-existent-file kill "$PID" # Test varlinkctl's --exec fd passing logic properly -assert_eq "$(varlinkctl --exec call /run/systemd/machine/io.systemd.Machine io.systemd.Machine.Open '{"name": ".host", "mode": "shell", "user": "root", "path": "/bin/bash", "args": ["/bin/bash", "-c", "echo $((7 + 8))"]}' -- bash -c 'read -r -N 2 x <&3 ; echo "$x"')" 15 +assert_eq "$(varlinkctl --exec call /run/systemd/machine/io.systemd.Machine io.systemd.Machine.Open '{"name": ".host", "mode": "shell", "user": "root", "path": "/bin/bash", "args": ["/bin/bash", "-c", "echo $((7 + 8))"], "environment": ["TERM=dumb"]}' -- bash -c 'read -r -N 2 x <&3 ; echo "$x"')" 15 # test io.systemd.Machine.MapFrom varlinkctl call /run/systemd/machine/io.systemd.Machine io.systemd.Machine.MapFrom '{"name": "long-running", "uid":0, "gid": 0}'