]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
core: also issue OSC 3008 from service context 35224/head
authorLennart Poettering <lennart@poettering.net>
Fri, 31 Jan 2025 16:40:46 +0000 (17:40 +0100)
committerLennart Poettering <lennart@poettering.net>
Thu, 27 Feb 2025 14:17:34 +0000 (15:17 +0100)
(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.)

src/core/exec-invoke.c
src/core/execute.c
src/core/execute.h
src/core/service.c
test/units/TEST-13-NSPAWN.machined.sh

index 490b3a522ae1197739519133f2b01ecdf3ac616d..94157a9e99e40a84fa9781a292b82507db1f76cf 100644 (file)
@@ -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;
index 7d99e72328852a87409e8b67c20dd2eee7e4b0f0..a7e8b3340c0da1c1fafdd715002fb8b34e42f8de 100644 (file)
@@ -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
index abfa31afcb60cfabe0005ab8a21a5cbc6bdfb837..8128c4c92868aa9a63206f4e9521530640b8bc65 100644 (file)
@@ -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);
index 112e4370a5a2b68053508a132851794087664596..12b367ccc83ef94b6cdeae37b2d7284ebdfbdc68 100644 (file)
@@ -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) {
index 4875e48f8095c3321beab9eaf901d973f8b72b7c..d8c15dfcfb8ce8447db198c7f9db3f07a00fdf4d 100755 (executable)
@@ -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}'