From cace9cf6f65422fbbc78c11515ceba56fd00f87a Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Mon, 11 Aug 2025 15:58:31 +0900 Subject: [PATCH 01/13] machinectl: set TERM=dumb when running on a dumb terminal or with a pipe Fixes #38527. --- src/machine/machinectl.c | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/src/machine/machinectl.c b/src/machine/machinectl.c index 4e3138b2ff..fd37bde874 100644 --- a/src/machine/machinectl.c +++ b/src/machine/machinectl.c @@ -1400,18 +1400,25 @@ static int shell_machine(int argc, char *argv[], void *userdata) { return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "Shell only supported on local machines."); - /* Pass $TERM & Co. to shell session, if not explicitly specified. */ - FOREACH_STRING(v, "TERM=", "COLORTERM=", "NO_COLOR=") { - if (strv_find_prefix(arg_setenv, v)) - continue; + if (terminal_is_dumb()) { + /* Set TERM=dumb if we are running on a dumb terminal or with a pipe. + * Otherwise, we will get unwanted OSC sequences. */ + if (!strv_find_prefix(arg_setenv, "TERM=")) + if (strv_extend(&arg_setenv, "TERM=dumb") < 0) + return log_oom(); + } else + /* Pass $TERM & Co. to shell session, if not explicitly specified. */ + FOREACH_STRING(v, "TERM=", "COLORTERM=", "NO_COLOR=") { + if (strv_find_prefix(arg_setenv, v)) + continue; - const char *t = strv_find_prefix(environ, v); - if (!t) - continue; + const char *t = strv_find_prefix(environ, v); + if (!t) + continue; - if (strv_extend(&arg_setenv, t) < 0) - return log_oom(); - } + if (strv_extend(&arg_setenv, t) < 0) + return log_oom(); + } (void) polkit_agent_open_if_enabled(arg_transport, arg_ask_password); From f79f89c202edf3f91ce15330faafcad582abc89e Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Mon, 11 Aug 2025 16:41:29 +0900 Subject: [PATCH 02/13] profile: do not prompt OSC sequences when running on a dumb terminal --- profile.d/80-systemd-osc-context.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/profile.d/80-systemd-osc-context.sh b/profile.d/80-systemd-osc-context.sh index 85983dc68d..ee37c2507a 100644 --- a/profile.d/80-systemd-osc-context.sh +++ b/profile.d/80-systemd-osc-context.sh @@ -53,7 +53,7 @@ __systemd_osc_context_precmdline() { read -r systemd_osc_context_cmd_id Date: Mon, 11 Aug 2025 16:35:02 +0900 Subject: [PATCH 03/13] nspawn: always set TERM=dumb when running with a pipe Otherwise, we will get unexpected OSC sequences. --- src/nspawn/nspawn.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c index 8013aa94c3..22bbdc1132 100644 --- a/src/nspawn/nspawn.c +++ b/src/nspawn/nspawn.c @@ -3551,7 +3551,7 @@ static int inner_child( envp[n_env++] = strjoina("container=", arg_container_service_name); /* Propagate $TERM & Co. unless we are invoked in pipe mode and stdin/stdout/stderr don't refer to a TTY */ - if (arg_console_mode != CONSOLE_PIPE || on_tty()) { + if (arg_console_mode != CONSOLE_PIPE && !terminal_is_dumb()) FOREACH_STRING(v, "TERM=", "COLORTERM=", "NO_COLOR=") { char *t = strv_find_prefix(environ, v); if (!t) @@ -3559,7 +3559,7 @@ static int inner_child( envp[n_env++] = t; } - } else + else envp[n_env++] = (char*) "TERM=dumb"; if (home || !uid_is_valid(arg_uid) || arg_uid == 0) From 18924bc784251ee5a2b27a658c9fbf974036f851 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Mon, 11 Aug 2025 17:21:38 +0900 Subject: [PATCH 04/13] core: do not print OSC sequence on reverting TTY settings when running on a dumb terminal Like we do in prepare_terminal() in exec-invoke.c. --- src/core/execute.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/execute.c b/src/core/execute.c index a4de33baec..6cfa3fc6b5 100644 --- a/src/core/execute.c +++ b/src/core/execute.c @@ -180,7 +180,7 @@ void exec_context_tty_reset(const ExecContext *context, const ExecParameters *pa if (r < 0) log_debug_errno(r, "Failed to configure TTY dimensions, ignoring: %m"); - if (!sd_id128_is_null(invocation_id)) { + if (!sd_id128_is_null(invocation_id) && exec_context_shall_ansi_seq_reset(context)) { sd_id128_t context_id; r = osc_context_id_from_invocation_id(invocation_id, &context_id); From da34c27bb12bf3dabae14c3673e0943b05329195 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Tue, 12 Aug 2025 16:21:48 +0900 Subject: [PATCH 05/13] core: make is_terminal_input() and friends inline Then, rename them to exec_input_is_terminal() and so on. --- src/core/exec-invoke.c | 42 +++++++++++------------------------------- src/core/execute.c | 24 +++++------------------- src/core/execute.h | 20 ++++++++++++++++++++ 3 files changed, 36 insertions(+), 50 deletions(-) diff --git a/src/core/exec-invoke.c b/src/core/exec-invoke.c index ddf888ee8a..0a5f455369 100644 --- a/src/core/exec-invoke.c +++ b/src/core/exec-invoke.c @@ -128,26 +128,6 @@ static int flag_fds( return 0; } -static bool is_terminal_input(ExecInput i) { - return IN_SET(i, - EXEC_INPUT_TTY, - EXEC_INPUT_TTY_FORCE, - EXEC_INPUT_TTY_FAIL); -} - -static bool is_terminal_output(ExecOutput o) { - return IN_SET(o, - EXEC_OUTPUT_TTY, - EXEC_OUTPUT_KMSG_AND_CONSOLE, - EXEC_OUTPUT_JOURNAL_AND_CONSOLE); -} - -static bool is_kmsg_output(ExecOutput o) { - return IN_SET(o, - EXEC_OUTPUT_KMSG, - EXEC_OUTPUT_KMSG_AND_CONSOLE); -} - static int open_null_as(int flags, int nfd) { int fd; @@ -252,8 +232,8 @@ static int connect_logger_as( context->syslog_priority, !!context->syslog_level_prefix, false, - is_kmsg_output(output), - is_terminal_output(output)) < 0) + exec_output_is_kmsg(output), + exec_output_is_terminal(output)) < 0) return -errno; return move_fd(TAKE_FD(fd), nfd, false); @@ -325,7 +305,7 @@ static int fixup_input( std_input = context->std_input; - if (is_terminal_input(std_input) && !apply_tty_stdin) + if (exec_input_is_terminal(std_input) && !apply_tty_stdin) return EXEC_INPUT_NULL; if (std_input == EXEC_INPUT_SOCKET && socket_fd < 0) @@ -531,7 +511,7 @@ static int setup_output( if (e == EXEC_OUTPUT_INHERIT && o == EXEC_OUTPUT_INHERIT && i == EXEC_INPUT_NULL && - !is_terminal_input(context->std_input) && + !exec_input_is_terminal(context->std_input) && getppid() != 1) return fileno; @@ -543,7 +523,7 @@ static int setup_output( } else if (o == EXEC_OUTPUT_INHERIT) { /* If input got downgraded, inherit the original value */ - if (i == EXEC_INPUT_NULL && is_terminal_input(context->std_input)) + if (i == EXEC_INPUT_NULL && exec_input_is_terminal(context->std_input)) return open_terminal_as(exec_context_tty_path(context), O_WRONLY, fileno); /* If the input is connected to anything that's not a /dev/null or a data fd, inherit that... */ @@ -564,7 +544,7 @@ static int setup_output( return open_null_as(O_WRONLY, fileno); case EXEC_OUTPUT_TTY: - if (is_terminal_input(i)) + if (exec_input_is_terminal(i)) return RET_NERRNO(dup2(STDIN_FILENO, fileno)); return open_terminal_as(exec_context_tty_path(context), O_WRONLY, fileno); @@ -4880,8 +4860,8 @@ static void prepare_terminal( assert(p); /* We only try to reset things if we there's the chance our stdout points to a TTY */ - if (!(is_terminal_output(context->std_output) || - (context->std_output == EXEC_OUTPUT_INHERIT && is_terminal_input(context->std_input)) || + if (!(exec_output_is_terminal(context->std_output) || + (context->std_output == EXEC_OUTPUT_INHERIT && exec_input_is_terminal(context->std_input)) || context->std_output == EXEC_OUTPUT_NAMED_FD || p->stdout_fd >= 0)) return; @@ -4921,9 +4901,9 @@ static int setup_term_environment(const ExecContext *context, char ***env) { return 0; /* Do we need $TERM at all? */ - if (!is_terminal_input(context->std_input) && - !is_terminal_output(context->std_output) && - !is_terminal_output(context->std_error) && + if (!exec_input_is_terminal(context->std_input) && + !exec_output_is_terminal(context->std_output) && + !exec_output_is_terminal(context->std_error) && !context->tty_path) return 0; diff --git a/src/core/execute.c b/src/core/execute.c index 6cfa3fc6b5..b998bdb367 100644 --- a/src/core/execute.c +++ b/src/core/execute.c @@ -65,20 +65,6 @@ #include "utmp-wtmp.h" #include "vpick.h" -static bool is_terminal_input(ExecInput i) { - return IN_SET(i, - EXEC_INPUT_TTY, - EXEC_INPUT_TTY_FORCE, - EXEC_INPUT_TTY_FAIL); -} - -static bool is_terminal_output(ExecOutput o) { - return IN_SET(o, - EXEC_OUTPUT_TTY, - EXEC_OUTPUT_KMSG_AND_CONSOLE, - EXEC_OUTPUT_JOURNAL_AND_CONSOLE); -} - const char* exec_context_tty_path(const ExecContext *context) { assert(context); @@ -151,8 +137,8 @@ void exec_context_tty_reset(const ExecContext *context, const ExecParameters *pa if (parameters && parameters->stdout_fd >= 0 && isatty_safe(parameters->stdout_fd)) fd = parameters->stdout_fd; - else if (path && (context->tty_path || is_terminal_input(context->std_input) || - is_terminal_output(context->std_output) || is_terminal_output(context->std_error))) { + else if (path && (context->tty_path || exec_input_is_terminal(context->std_input) || + exec_output_is_terminal(context->std_output) || exec_output_is_terminal(context->std_error))) { fd = _fd = open_terminal(path, O_RDWR|O_NOCTTY|O_CLOEXEC|O_NONBLOCK); if (fd < 0) return (void) log_debug_errno(fd, "Failed to open terminal '%s', ignoring: %m", path); @@ -1000,9 +986,9 @@ static bool exec_context_may_touch_tty(const ExecContext *ec) { return ec->tty_reset || ec->tty_vhangup || ec->tty_vt_disallocate || - is_terminal_input(ec->std_input) || - is_terminal_output(ec->std_output) || - is_terminal_output(ec->std_error); + exec_input_is_terminal(ec->std_input) || + exec_output_is_terminal(ec->std_output) || + exec_output_is_terminal(ec->std_error); } bool exec_context_may_touch_console(const ExecContext *ec) { diff --git a/src/core/execute.h b/src/core/execute.h index 64e8896062..ce6483260a 100644 --- a/src/core/execute.h +++ b/src/core/execute.h @@ -458,6 +458,26 @@ typedef struct ExecParameters { .pidref_transport_fd = -EBADF, \ } +static inline bool exec_input_is_terminal(ExecInput i) { + return IN_SET(i, + EXEC_INPUT_TTY, + EXEC_INPUT_TTY_FORCE, + EXEC_INPUT_TTY_FAIL); +} + +static inline bool exec_output_is_terminal(ExecOutput o) { + return IN_SET(o, + EXEC_OUTPUT_TTY, + EXEC_OUTPUT_KMSG_AND_CONSOLE, + EXEC_OUTPUT_JOURNAL_AND_CONSOLE); +} + +static inline bool exec_output_is_kmsg(ExecOutput o) { + return IN_SET(o, + EXEC_OUTPUT_KMSG, + EXEC_OUTPUT_KMSG_AND_CONSOLE); +} + int exec_spawn( Unit *unit, ExecCommand *command, From 379d9ae222c52f93692e06d5b33fb341791b9688 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Tue, 12 Aug 2025 16:54:59 +0900 Subject: [PATCH 06/13] core: do not touch tty when StandardOutput=/StandardError=journal+console/kmsg+console --- src/core/exec-invoke.c | 7 ++----- src/core/execute.c | 7 +++---- src/core/execute.h | 10 ++++++++++ 3 files changed, 15 insertions(+), 9 deletions(-) diff --git a/src/core/exec-invoke.c b/src/core/exec-invoke.c index 0a5f455369..1e2945eb91 100644 --- a/src/core/exec-invoke.c +++ b/src/core/exec-invoke.c @@ -4860,7 +4860,7 @@ static void prepare_terminal( assert(p); /* We only try to reset things if we there's the chance our stdout points to a TTY */ - if (!(exec_output_is_terminal(context->std_output) || + if (!(context->std_output == EXEC_OUTPUT_TTY || (context->std_output == EXEC_OUTPUT_INHERIT && exec_input_is_terminal(context->std_input)) || context->std_output == EXEC_OUTPUT_NAMED_FD || p->stdout_fd >= 0)) @@ -4901,10 +4901,7 @@ static int setup_term_environment(const ExecContext *context, char ***env) { return 0; /* Do we need $TERM at all? */ - if (!exec_input_is_terminal(context->std_input) && - !exec_output_is_terminal(context->std_output) && - !exec_output_is_terminal(context->std_error) && - !context->tty_path) + if (!exec_context_has_tty(context)) return 0; const char *tty_path = exec_context_tty_path(context); diff --git a/src/core/execute.c b/src/core/execute.c index b998bdb367..fa63a6bee0 100644 --- a/src/core/execute.c +++ b/src/core/execute.c @@ -137,8 +137,7 @@ void exec_context_tty_reset(const ExecContext *context, const ExecParameters *pa if (parameters && parameters->stdout_fd >= 0 && isatty_safe(parameters->stdout_fd)) fd = parameters->stdout_fd; - else if (path && (context->tty_path || exec_input_is_terminal(context->std_input) || - exec_output_is_terminal(context->std_output) || exec_output_is_terminal(context->std_error))) { + else if (path && exec_context_has_tty(context)) { fd = _fd = open_terminal(path, O_RDWR|O_NOCTTY|O_CLOEXEC|O_NONBLOCK); if (fd < 0) return (void) log_debug_errno(fd, "Failed to open terminal '%s', ignoring: %m", path); @@ -987,8 +986,8 @@ static bool exec_context_may_touch_tty(const ExecContext *ec) { ec->tty_vhangup || ec->tty_vt_disallocate || exec_input_is_terminal(ec->std_input) || - exec_output_is_terminal(ec->std_output) || - exec_output_is_terminal(ec->std_error); + ec->std_output == EXEC_OUTPUT_TTY || + ec->std_error == EXEC_OUTPUT_TTY; } bool exec_context_may_touch_console(const ExecContext *ec) { diff --git a/src/core/execute.h b/src/core/execute.h index ce6483260a..2e30374830 100644 --- a/src/core/execute.h +++ b/src/core/execute.h @@ -478,6 +478,16 @@ static inline bool exec_output_is_kmsg(ExecOutput o) { EXEC_OUTPUT_KMSG_AND_CONSOLE); } +static inline bool exec_context_has_tty(const ExecContext *context) { + assert(context); + + return + context->tty_path || + exec_input_is_terminal(context->std_input) || + context->std_output == EXEC_OUTPUT_TTY || + context->std_error == EXEC_OUTPUT_TTY; +} + int exec_spawn( Unit *unit, ExecCommand *command, From d62adb5554c25a495d34234a593d3a20c1922e34 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Wed, 13 Aug 2025 11:29:36 +0900 Subject: [PATCH 07/13] core/execute: add one more FIXME comment --- src/core/execute.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/core/execute.c b/src/core/execute.c index fa63a6bee0..c384e9dd63 100644 --- a/src/core/execute.c +++ b/src/core/execute.c @@ -1009,6 +1009,9 @@ bool exec_context_shall_ansi_seq_reset(const ExecContext *c) { if (!c->tty_reset) return false; + /* FIXME: + * On invocation, we generate $TERM based on settings for StandardOutput= and friends and the kernel + * command line options, or propagate $TERM from the service manager. See setup_term_environment(). */ return !streq_ptr(strv_env_get(c->environment, "TERM"), "dumb"); } From 3796391497c50f7d04eccdeaa07258cead076d9f Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Wed, 13 Aug 2025 14:17:10 +0900 Subject: [PATCH 08/13] pretty-print: show progress bar only when we are running on a TTY Otherwise, when a command is running with e.g. StandardError=journal+console, journal contains [xxxB blob data]: ``` [ 5.628796] TEST-13-NSPAWN.sh[299]: + importctl import-raw --class=confext /var/tmp/importtest [ 5.632350] systemd-importd[302]: Successfully forked off '(sd-transfer)' as PID 319. [ 5.633671] TEST-13-NSPAWN.sh[318]: [83B blob data] [ 5.632598] (sd-transfer)[319]: Calling: /usr/lib/systemd/systemd-import raw --class confext - importtest [ 5.637769] systemd-importd[302]: (transfer1) Importing '/var/tmp/importtest', saving as 'importtest'. [ 5.637947] TEST-13-NSPAWN.sh[318]: [82B blob data] [ 5.638313] TEST-13-NSPAWN.sh[318]: [75B blob data] [ 5.638151] systemd-importd[302]: (transfer1) Operating on image directory '/var/lib/confexts'. [ 5.638863] systemd-importd[302]: (transfer1) Imported 40%. [ 5.638882] systemd-importd[302]: (transfer1) Wrote 40K. [ 5.639653] TEST-13-NSPAWN.sh[318]: [39B blob data] [ 5.639653] TEST-13-NSPAWN.sh[318]: [36B blob data] [ 5.639653] TEST-13-NSPAWN.sh[318]: [59B blob data] [ 5.639653] TEST-13-NSPAWN.sh[318]: [34B blob data] [ 5.638894] systemd-importd[302]: (transfer1) Operation completed successfully. [ 5.640760] TEST-13-NSPAWN.sh[318]: [25B blob data] [ 5.638902] systemd-importd[302]: (transfer1) Exiting. ``` The blob data entries are something like the following: ``` [ 5.628796] TEST-13-NSPAWN.sh[299]: + importctl import-raw --class=confext /var/tmp/importtest [ 5.632350] systemd-importd[302]: Successfully forked off '(sd-transfer)' as PID 319. [ 5.633671] TEST-13-NSPAWN.sh[318]: ^M ^MEnqueued transfer job 1. Press C-c to continue download in background. [ 5.632598] (sd-transfer)[319]: Calling: /usr/lib/systemd/systemd-import raw --class confext - importtest [ 5.637769] systemd-importd[302]: (transfer1) Importing '/var/tmp/importtest', saving as 'importtest'. [ 5.637947] TEST-13-NSPAWN.sh[318]: ^MTotal: 0%^M ^MImporting '/var/tmp/importtest', saving as 'importtest'. [ 5.638313] TEST-13-NSPAWN.sh[318]: ^MTotal: 0%^M ^MOperating on image directory '/var/lib/confexts'. [ 5.638151] systemd-importd[302]: (transfer1) Operating on image directory '/var/lib/confexts'. [ 5.638863] systemd-importd[302]: (transfer1) Imported 40%. [ 5.638882] systemd-importd[302]: (transfer1) Wrote 40K. [ 5.639653] TEST-13-NSPAWN.sh[318]: ^MTotal: 0%^M ^MImported 40%. [ 5.639653] TEST-13-NSPAWN.sh[318]: ^MTotal: 0%^M ^MWrote 40K. [ 5.639653] TEST-13-NSPAWN.sh[318]: ^MTotal: 0%^M ^MOperation completed successfully. [ 5.639653] TEST-13-NSPAWN.sh[318]: ^MTotal: 0%^M ^MExiting. [ 5.638894] systemd-importd[302]: (transfer1) Operation completed successfully. [ 5.640760] TEST-13-NSPAWN.sh[318]: ^MTotal: 0%^MTotal: 40% [ 5.638902] systemd-importd[302]: (transfer1) Exiting. ``` Fixes #38552. --- src/shared/pretty-print.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/shared/pretty-print.c b/src/shared/pretty-print.c index cbcf2a4be2..c7e77fd8e2 100644 --- a/src/shared/pretty-print.c +++ b/src/shared/pretty-print.c @@ -530,6 +530,9 @@ bool shall_tint_background(void) { } void draw_progress_bar_unbuffered(const char *prefix, double percentage) { + if (!on_tty()) + return; + fputc('\r', stderr); if (prefix) { fputs(prefix, stderr); @@ -593,6 +596,9 @@ void draw_progress_bar_unbuffered(const char *prefix, double percentage) { } void clear_progress_bar_unbuffered(const char *prefix) { + if (!on_tty()) + return; + fputc('\r', stderr); if (terminal_is_dumb()) @@ -609,6 +615,9 @@ void clear_progress_bar_unbuffered(const char *prefix) { } void draw_progress_bar(const char *prefix, double percentage) { + if (!on_tty()) + return; + /* We are going output a bunch of small strings that shall appear as a single line to STDERR which is * unbuffered by default. Let's temporarily turn on full buffering, so that this is passed to the tty * as a single buffer, to make things more efficient. */ @@ -621,6 +630,9 @@ int draw_progress_barf(double percentage, const char *prefixf, ...) { va_list ap; int r; + if (!on_tty()) + return 0; + va_start(ap, prefixf); r = vasprintf(&s, prefixf, ap); va_end(ap); @@ -633,6 +645,9 @@ int draw_progress_barf(double percentage, const char *prefixf, ...) { } void clear_progress_bar(const char *prefix) { + if (!on_tty()) + return; + WITH_BUFFERED_STDERR; clear_progress_bar_unbuffered(prefix); } From 00085ba6c2837bba10a25ea38cc9ead065867f2c Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Wed, 13 Aug 2025 14:35:51 +0900 Subject: [PATCH 09/13] import,sysupdate: make notify event processed before SIGCHLD of worker processes This fixes the following warning: ``` [ 5.628796] TEST-13-NSPAWN.sh[299]: + importctl import-raw --class=confext /var/tmp/importtest (snip) [ 5.638894] systemd-importd[302]: (transfer1) Operation completed successfully. [ 5.640760] TEST-13-NSPAWN.sh[318]: ^MTotal: 0%^MTotal: 40% [ 5.638902] systemd-importd[302]: (transfer1) Exiting. [ 5.638931] systemd-importd[302]: Got percentage from client: 40% [ 5.638956] systemd-importd[302]: Transfer process succeeded. [ 5.638988] systemd-importd[302]: Got notification datagram from unexpected peer, ignoring. ``` --- src/import/importd.c | 2 +- src/sysupdate/sysupdated.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/import/importd.c b/src/import/importd.c index 84cc9ca86a..f2715691ab 100644 --- a/src/import/importd.c +++ b/src/import/importd.c @@ -721,7 +721,7 @@ static int manager_new(Manager **ret) { r = notify_socket_prepare( m->event, - SD_EVENT_PRIORITY_NORMAL, + SD_EVENT_PRIORITY_NORMAL - 1, /* Make this processed before SIGCHLD. */ manager_on_notify, m, &m->notify_socket_path); diff --git a/src/sysupdate/sysupdated.c b/src/sysupdate/sysupdated.c index cc45ca0657..b1438ff825 100644 --- a/src/sysupdate/sysupdated.c +++ b/src/sysupdate/sysupdated.c @@ -1746,7 +1746,7 @@ static int manager_new(Manager **ret) { r = notify_socket_prepare( m->event, - SD_EVENT_PRIORITY_NORMAL, + SD_EVENT_PRIORITY_NORMAL - 1, /* Make this processed before SIGCHLD. */ manager_on_notify, m, &m->notify_socket_path); From defac931c006b6653215f7f797e26fb47b356a3f Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Wed, 13 Aug 2025 15:22:41 +0900 Subject: [PATCH 10/13] import: align table --- src/import/import-compress.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/import/import-compress.c b/src/import/import-compress.c index 012fd2c3ed..eb44fc9d60 100644 --- a/src/import/import-compress.c +++ b/src/import/import-compress.c @@ -589,15 +589,15 @@ int import_compress_finish(ImportCompress *c, void **buffer, size_t *buffer_size } static const char* const import_compress_type_table[_IMPORT_COMPRESS_TYPE_MAX] = { - [IMPORT_COMPRESS_UNKNOWN] = "unknown", + [IMPORT_COMPRESS_UNKNOWN] = "unknown", [IMPORT_COMPRESS_UNCOMPRESSED] = "uncompressed", - [IMPORT_COMPRESS_XZ] = "xz", - [IMPORT_COMPRESS_GZIP] = "gzip", + [IMPORT_COMPRESS_XZ] = "xz", + [IMPORT_COMPRESS_GZIP] = "gzip", #if HAVE_BZIP2 - [IMPORT_COMPRESS_BZIP2] = "bzip2", + [IMPORT_COMPRESS_BZIP2] = "bzip2", #endif #if HAVE_ZSTD - [IMPORT_COMPRESS_ZSTD] = "zstd", + [IMPORT_COMPRESS_ZSTD] = "zstd", #endif }; From 2633ed01caa93a7bf909fc2c6ee4af1ff6fb48d4 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Wed, 13 Aug 2025 15:26:35 +0900 Subject: [PATCH 11/13] import: add a debugging log of importing blob This should be helpful for debugging issue #38524. --- src/import/import-compress.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/import/import-compress.c b/src/import/import-compress.c index eb44fc9d60..666a2c3aab 100644 --- a/src/import/import-compress.c +++ b/src/import/import-compress.c @@ -4,6 +4,7 @@ #include #include "import-compress.h" +#include "log.h" #include "string-table.h" void import_compress_free(ImportCompress *c) { @@ -104,6 +105,7 @@ int import_uncompress_detect(ImportCompress *c, const void *data, size_t size) { c->encoding = false; + log_debug("Detected compression type: %s", import_compress_type_to_string(c->type)); return 1; } From 535539222d0636fade66236d4d1603f49a6c7a13 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Wed, 13 Aug 2025 15:57:15 +0900 Subject: [PATCH 12/13] TEST-72-SYSUPDATE: make randomly generated image file not have compression header MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Otherwise, the generated image may be wrongly detected as compressed, and importing the image may fail: ``` [ 35.194578] TEST-72-SYSUPDATE.sh[411]: + dd if=/dev/urandom of=/var/tmp/test-72-N7uTeO/source/part1-v5.raw bs=4096 count=2048 [ 35.236342] TEST-72-SYSUPDATE.sh[1075]: 2048+0 records in [ 35.236342] TEST-72-SYSUPDATE.sh[1075]: 2048+0 records out [ 35.236342] TEST-72-SYSUPDATE.sh[1075]: 8388608 bytes (8.4 MB, 8.0 MiB) copied, 0.0408601 s, 205 MB/s (snip) [ 35.948634] TEST-72-SYSUPDATE.sh[1085]: \ Acquiring /var/tmp/test-72-N7uTeO/source/part1-v5.raw → /proc/self/fd/3p2... [ 35.952878] TEST-72-SYSUPDATE.sh[1085]: Successfully forked off '(sd-import-raw)' as PID 1089. [ 35.958952] TEST-72-SYSUPDATE.sh[1089]: Importing '/var/tmp/test-72-N7uTeO/source/part1-v5.raw', saving at offset 9437184 in '/dev/loop0'. [ 35.959575] TEST-72-SYSUPDATE.sh[1089]: Failed to decode and write: Input/output error [ 35.959575] TEST-72-SYSUPDATE.sh[1089]: Exiting. ``` Fixes #38524. --- test/units/TEST-72-SYSUPDATE.sh | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/test/units/TEST-72-SYSUPDATE.sh b/test/units/TEST-72-SYSUPDATE.sh index e5c62c635e..57510b9638 100755 --- a/test/units/TEST-72-SYSUPDATE.sh +++ b/test/units/TEST-72-SYSUPDATE.sh @@ -61,8 +61,11 @@ new_version() { local sector_size="${1:?}" local version="${2:?}" - # Create a pair of random partition payloads, and compress one - dd if=/dev/urandom of="$WORKDIR/source/part1-$version.raw" bs="$sector_size" count=2048 + # Create a pair of random partition payloads, and compress one. + # To make not the initial bytes of part1-xxx.raw accidentally match one of the compression header, + # let's make the first sector filled by zero. + dd if=/dev/zero of="$WORKDIR/source/part1-$version.raw" bs="$sector_size" count=1 + dd if=/dev/urandom of="$WORKDIR/source/part1-$version.raw" bs="$sector_size" count=2047 conv=notrunc oflag=append dd if=/dev/urandom of="$WORKDIR/source/part2-$version.raw" bs="$sector_size" count=2048 gzip -k -f "$WORKDIR/source/part2-$version.raw" From 53878b5b3e50539d40d5a5da9da0968e84770bf8 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Wed, 13 Aug 2025 23:53:13 +0900 Subject: [PATCH 13/13] TEST-72-SYSUPDATE: fix indentation and drop space in blank line --- test/units/TEST-72-SYSUPDATE.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/units/TEST-72-SYSUPDATE.sh b/test/units/TEST-72-SYSUPDATE.sh index 57510b9638..93a5ffb87f 100755 --- a/test/units/TEST-72-SYSUPDATE.sh +++ b/test/units/TEST-72-SYSUPDATE.sh @@ -54,7 +54,7 @@ at_exit() { trap at_exit EXIT update_checksums() { - (cd "$WORKDIR/source" && sha256sum uki* part* dir-*.tar.gz >SHA256SUMS) + (cd "$WORKDIR/source" && sha256sum uki* part* dir-*.tar.gz >SHA256SUMS) } new_version() { @@ -357,7 +357,7 @@ EOF updatectl check rm -r /run/sysupdate.test.d fi - + # Create seventh version, and update through a file:// URL. This should be # almost as good as testing HTTP, but is simpler for us to set up. file:// is # abstracted in curl for us, and since our main goal is to test our own code