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:
commit
d54196a4cd
14
.github/workflows/mkosi.yml
vendored
14
.github/workflows/mkosi.yml
vendored
@ -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: ""
|
||||
|
113
src/run/run.c
113
src/run/run.c
@ -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();
|
||||
|
@ -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
|
||||
|
@ -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'
|
||||
|
Loading…
x
Reference in New Issue
Block a user