1
0
mirror of https://github.com/systemd/systemd.git synced 2025-03-19 22:50:17 +03:00

Fixes several recent CI issues (#36691)

- Fixes a race in systemd-run caused by
b7ba8d55b8e413ff326abc4814b92d42b8d3c3c3, which causes issue #36679.
- Skip verifying masked units in TEST-23.
- Avoid false-positive ASan warning by switching sanitizer run from
Fedora rawhide to Fedora 41, caused by recent update from
llvm-19.1.7-11.fc43 to llvm-20.1.0-1.fc43. Hopefully issue #36678 should
be fixed.

Closes #36678.
Closes #36679.
This commit is contained in:
Lennart Poettering 2025-03-12 15:32:58 +01:00 committed by GitHub
commit d54196a4cd
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 65 additions and 71 deletions

View File

@ -80,19 +80,19 @@ jobs:
skip: TEST-21-DFUZZER
- distro: fedora
release: "41"
sanitizers: address,undefined
llvm: 1
cflags: "-Og"
relabel: yes
vm: 0
- distro: fedora
release: rawhide
sanitizers: ""
llvm: 0
cflags: "-Og"
relabel: yes
vm: 0
skip: TEST-21-DFUZZER
- distro: fedora
release: rawhide
sanitizers: address,undefined
llvm: 1
cflags: "-Og"
relabel: yes
vm: 0
- distro: opensuse
release: tumbleweed
sanitizers: ""

View File

@ -1568,12 +1568,11 @@ typedef struct RunContext {
sd_bus *bus;
sd_bus_slot *match_properties_changed;
sd_bus_slot *match_disconnected;
sd_bus_slot *match_job_removed;
sd_event_source *retry_timer;
/* Current state of the unit */
char *active_state;
bool has_job;
char *job;
/* The exit data of the unit */
uint64_t inactive_exit_usec;
@ -1594,6 +1593,7 @@ static int run_context_update(RunContext *c);
static int run_context_attach_bus(RunContext *c, sd_bus *bus);
static void run_context_detach_bus(RunContext *c);
static int run_context_reconnect(RunContext *c);
static int run_context_setup_ptyfwd(RunContext *c);
static void run_context_done(RunContext *c) {
assert(c);
@ -1605,6 +1605,7 @@ static void run_context_done(RunContext *c) {
c->event = sd_event_unref(c->event);
free(c->active_state);
free(c->job);
free(c->result);
free(c->unit);
free(c->bus_path);
@ -1661,12 +1662,44 @@ static int run_context_reconnect(RunContext *c) {
return run_context_update(c);
}
static int run_context_check_started(RunContext *c) {
int r;
assert(c);
if (!c->start_job)
return 0; /* Already started? */
if (streq_ptr(c->start_job, c->job))
return 0; /* The start job is still active. */
/* The start job is finished. */
c->start_job = mfree(c->start_job);
/* Setup ptyfwd now if --pty-late is specified. */
r = run_context_setup_ptyfwd(c);
if (r < 0) {
sd_event_exit(c->event, EXIT_FAILURE);
return r;
}
if (STRPTR_IN_SET(c->active_state, "inactive", "failed"))
return 0; /* Already finished or failed? */
/* Notify our caller that the service is now running, just in case. */
(void) sd_notifyf(/* unset_environment= */ false,
"READY=1\n"
"RUN_UNIT=%s",
c->unit);
return 0;
}
static void run_context_check_done(RunContext *c) {
assert(c);
bool done = STRPTR_IN_SET(c->active_state, "inactive", "failed") &&
!c->start_job && /* our start job */
!c->has_job; /* any other job */
!c->job; /* any other job */
if (done && c->forward) /* If the service is gone, it's time to drain the output */
done = pty_forward_drain(c->forward);
@ -1676,17 +1709,18 @@ static void run_context_check_done(RunContext *c) {
}
static int map_job(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
bool *b = userdata;
char **p = ASSERT_PTR(userdata);
const char *job;
uint32_t id;
int r;
assert(m);
r = sd_bus_message_read(m, "(uo)", &id, &job);
if (r < 0)
return r;
*b = id != 0 || !streq(job, "/");
return 0;
return free_and_strdup(p, id == 0 ? NULL : job);
}
static int run_context_update(RunContext *c) {
@ -1705,7 +1739,7 @@ static int run_context_update(RunContext *c) {
{ "IPEgressBytes", "t", NULL, offsetof(RunContext, ip_egress_bytes) },
{ "IOReadBytes", "t", NULL, offsetof(RunContext, io_read_bytes) },
{ "IOWriteBytes", "t", NULL, offsetof(RunContext, io_write_bytes) },
{ "Job", "(uo)", map_job, offsetof(RunContext, has_job) },
{ "Job", "(uo)", map_job, offsetof(RunContext, job) },
{}
};
@ -1744,6 +1778,10 @@ static int run_context_update(RunContext *c) {
return log_error_errno(r, "Failed to query unit state: %s", bus_error_message(&error, r));
}
r = run_context_check_started(c);
if (r < 0)
return r;
run_context_check_done(c);
return 0;
}
@ -1810,7 +1848,6 @@ static void run_context_detach_bus(RunContext *c) {
c->match_properties_changed = sd_bus_slot_unref(c->match_properties_changed);
c->match_disconnected = sd_bus_slot_unref(c->match_disconnected);
c->match_job_removed = sd_bus_slot_unref(c->match_job_removed);
}
static int pty_forward_handler(PTYForward *f, int rcode, void *userdata) {
@ -2041,39 +2078,6 @@ static int run_context_setup_ptyfwd(RunContext *c) {
return 0;
}
static int match_job_removed(sd_bus_message *m, void *userdata, sd_bus_error *error) {
RunContext *c = ASSERT_PTR(userdata);
const char *path;
int r;
assert(m);
r = sd_bus_message_read(m, "uoss", /* id = */ NULL, &path, /* unit= */ NULL, /* result= */ NULL);
if (r < 0) {
bus_log_parse_error(r);
return 0;
}
if (!streq_ptr(path, c->start_job))
return 0;
/* Notify our caller that the service is now running, just in case. */
(void) sd_notifyf(/* unset_environment= */ false,
"READY=1\n"
"RUN_UNIT=%s",
c->unit);
r = run_context_setup_ptyfwd(c);
if (r < 0)
return sd_event_exit(c->event, r);
c->start_job = mfree(c->start_job);
c->match_job_removed = sd_bus_slot_unref(c->match_job_removed);
run_context_check_done(c);
return 0;
}
static int start_transient_service(sd_bus *bus) {
_cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL;
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
@ -2177,27 +2181,10 @@ static int start_transient_service(sd_bus *bus) {
* lets skip this however, because we should start that already when the start job is running, and
* there's little point in waiting for the start job to complete in that case anyway, as we'll wait
* for EOF anyway, which is going to be much later. */
if (!arg_no_block) {
if (arg_stdio == ARG_STDIO_NONE) {
r = bus_wait_for_jobs_new(bus, &w);
if (r < 0)
return log_error_errno(r, "Could not watch jobs: %m");
} else {
/* When we are a bus client we match by sender. Direct connections OTOH have no
* initialized sender field, and hence we ignore the sender then */
r = sd_bus_match_signal_async(
bus,
&c.match_job_removed,
sd_bus_is_bus_client(bus) ? "org.freedesktop.systemd1" : NULL,
"/org/freedesktop/systemd1",
"org.freedesktop.systemd1.Manager",
"JobRemoved",
match_job_removed,
/* add_callback= */ NULL,
&c);
if (r < 0)
return log_error_errno(r, "Failed to install JobRemove match: %m");
}
if (!arg_no_block && arg_stdio == ARG_STDIO_NONE) {
r = bus_wait_for_jobs_new(bus, &w);
if (r < 0)
return log_error_errno(r, "Could not watch jobs: %m");
}
r = make_transient_service_unit(bus, &m, c.unit, pty_path, peer_fd);
@ -2222,7 +2209,7 @@ static int start_transient_service(sd_bus *bus) {
arg_runtime_scope == RUNTIME_SCOPE_USER ? STRV_MAKE_CONST("--user") : NULL);
if (r < 0)
return r;
} else if (c.match_job_removed) {
} else if (!arg_no_block) {
c.start_job = strdup(object);
if (!c.start_job)
return log_oom();

View File

@ -41,5 +41,12 @@ for unit_file in "${UNIT_FILES[@]}"; do
continue
fi
# Skip masked unit files
resolved=$(readlink -f "$unit_file")
if [[ "$resolved" == "/dev/null" || "$(systemctl is-enabled "${resolved##*/}" 2>/dev/null || :)" == "masked" ]]; then
echo "$unit_file is masked, skipping"
continue
fi
systemd-analyze --recursive-errors=no --man=no verify "$unit_file"
done

View File

@ -284,4 +284,4 @@ if [[ -e /usr/lib/pam.d/systemd-run0 ]] || [[ -e /etc/pam.d/systemd-run0 ]]; the
fi
# Tests whether intermediate disconnects corrupt us (modified testcase from https://github.com/systemd/systemd/issues/27204)
assert_rc "37" systemd-run --unit=disconnecttest --wait --pipe --user -M testuser@.host bash -ec 'systemctl --user daemon-reexec; sleep 3; exit 37'
assert_rc "37" timeout 300 systemd-run --unit=disconnecttest --wait --pipe --user -M testuser@.host bash -ec 'systemctl --user daemon-reexec; sleep 3; exit 37'