1
0
mirror of https://github.com/systemd/systemd.git synced 2024-12-22 17:35:35 +03:00

Merge pull request #34202 from AdrianVovk/sysupdated-fixups

sysupdated: Bugfixes & improvements
This commit is contained in:
Adrian Vovk 2024-09-02 16:35:02 -04:00 committed by GitHub
commit 9b0647358f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 82 additions and 60 deletions

View File

@ -844,6 +844,7 @@ typedef struct CalloutContext {
TransferProgress callback;
PidRef pid;
const char *name;
int helper_errno;
void* userdata;
} CalloutContext;
@ -886,29 +887,34 @@ static int callout_context_new(const Transfer *t, const Instance *i, TransferPro
static int helper_on_exit(sd_event_source *s, const siginfo_t *si, void *userdata) {
_cleanup_(callout_context_freep) CalloutContext *ctx = ASSERT_PTR(userdata);
int code;
int r;
assert(s);
assert(si);
assert(ctx);
pidref_done(&ctx->pid);
if (si->si_code == CLD_EXITED) {
code = si->si_status;
if (code != EXIT_SUCCESS)
log_error("%s failed with exit status %i.", ctx->name, code);
else
if (si->si_status == EXIT_SUCCESS) {
r = 0;
log_debug("%s succeeded.", ctx->name);
} else if (ctx->helper_errno != 0) {
r = -ctx->helper_errno;
log_error_errno(r, "%s failed with exit status %i: %m", ctx->name, si->si_status);
} else {
code = -EPROTO;
r = -EPROTO;
log_error("%s failed with exit status %i.", ctx->name, si->si_status);
}
} else {
r = -EPROTO;
if (IN_SET(si->si_code, CLD_KILLED, CLD_DUMPED))
log_error("%s terminated by signal %s.", ctx->name, signal_to_string(si->si_status));
else
log_error("%s failed due to unknown reason.", ctx->name);
}
pidref_done(&ctx->pid);
return sd_event_exit(sd_event_source_get_event(s), code);
return sd_event_exit(sd_event_source_get_event(s), r);
}
static int helper_on_notify(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
@ -926,9 +932,10 @@ static int helper_on_notify(sd_event_source *s, int fd, uint32_t revents, void *
};
struct ucred *ucred;
CalloutContext *ctx = ASSERT_PTR(userdata);
char* progress_str;
char *progress_str, *errno_str;
int progress;
ssize_t n;
int r;
n = recvmsg_safe(fd, &msghdr, MSG_DONTWAIT|MSG_CMSG_CLOEXEC);
if (n < 0) {
@ -957,17 +964,32 @@ static int helper_on_notify(sd_event_source *s, int fd, uint32_t revents, void *
buf[n] = 0;
progress_str = find_line_startswith(buf, "X_IMPORT_PROGRESS=");
if (!progress_str)
return 0;
errno_str = find_line_startswith(buf, "ERRNO=");
truncate_nl(progress_str);
progress = parse_percent(progress_str);
if (progress < 0) {
log_warning("Got invalid percent value '%s', ignoring.", progress_str);
return 0;
if (errno_str) {
truncate_nl(errno_str);
r = parse_errno(errno_str);
if (r < 0)
log_warning_errno(r, "Got invalid errno value '%s', ignoring: %m", errno_str);
else {
ctx->helper_errno = r;
log_debug_errno(r, "Got errno from callout: %i (%m)", r);
}
}
return ctx->callback(ctx->transfer, ctx->instance, progress);
if (progress_str) {
truncate_nl(progress_str);
progress = parse_percent(progress_str);
if (progress < 0)
log_warning("Got invalid percent value '%s', ignoring.", progress_str);
else {
r = ctx->callback(ctx->transfer, ctx->instance, progress);
if (r < 0)
return r;
}
}
return 0;
}
static int run_callout(

View File

@ -210,7 +210,7 @@ static int job_parse_child_output(int _fd, sd_json_variant **ret) {
assert(ret);
if (fstat(fd, &st) < 0)
return log_error_errno(errno, "Failed to stat stdout fd: %m");
return log_debug_errno(errno, "Failed to stat stdout fd: %m");
assert(S_ISREG(st.st_mode));
@ -220,15 +220,15 @@ static int job_parse_child_output(int _fd, sd_json_variant **ret) {
}
if (lseek(fd, SEEK_SET, 0) == (off_t) -1)
return log_error_errno(errno, "Failed to seek to beginning of memfd: %m");
return log_debug_errno(errno, "Failed to seek to beginning of memfd: %m");
f = take_fdopen(&fd, "r");
if (!f)
return log_error_errno(errno, "Failed to reopen memfd: %m");
return log_debug_errno(errno, "Failed to reopen memfd: %m");
r = sd_json_parse_file(f, "stdout", 0, &v, NULL, NULL);
if (r < 0)
return log_error_errno(r, "Failed to parse JSON: %m");
return log_debug_errno(r, "Failed to parse JSON: %m");
*ret = TAKE_PTR(v);
return 0;
@ -248,6 +248,8 @@ static void job_on_ready(Job *j) {
if (!j->detach_cb)
return;
log_debug("Got READY=1 from job %" PRIu64", detaching.", j->id);
assert(j->dbus_msg);
msg = TAKE_PTR(j->dbus_msg);
@ -255,20 +257,18 @@ static void job_on_ready(Job *j) {
r = j->detach_cb(msg, j);
if (r < 0)
log_warning_errno(r, "Failed to run callback on job ready event, ignoring: %m");
log_warning_errno(r, "Failed to detach job %" PRIu64 ", ignoring: %m", j->id);
}
static void job_on_errno(Job *j, char *b) {
/* Take ownership of donated buffer */
_cleanup_free_ char *buf = TAKE_PTR(b);
static void job_on_errno(Job *j, const char *buf) {
int r;
assert(j);
assert_se(buf);
assert(buf);
r = parse_errno(buf);
if (r < 0) {
log_warning_errno(r, "Got invalid errno value, ignoring: %m");
log_warning_errno(r, "Got invalid errno value from job %" PRIu64 ", ignoring: %m", j->id);
return;
}
@ -277,14 +277,12 @@ static void job_on_errno(Job *j, char *b) {
log_debug_errno(r, "Got errno from job %" PRIu64 ": %i (%m)", j->id, r);
}
static void job_on_progress(Job *j, char *b) {
/* Take ownership of donated buffer */
_cleanup_free_ char *buf = TAKE_PTR(b);
static void job_on_progress(Job *j, const char *buf) {
unsigned progress;
int r;
assert(j);
assert_se(buf);
assert(buf);
r = safe_atou(buf, &progress);
if (r < 0 || progress > 100) {
@ -300,12 +298,12 @@ static void job_on_progress(Job *j, char *b) {
log_debug("Got percentage from job %" PRIu64 ": %u%%", j->id, j->progress_percent);
}
static void job_on_version(Job *j, char *version) {
static void job_on_version(Job *j, const char *version) {
assert(j);
assert_se(version);
assert(version);
/* Take ownership of donated memory */
free_and_replace(j->version, version);
if (free_and_strdup_warn(&j->version, version) < 0)
return;
log_debug("Got version from job %" PRIu64 ": %s ", j->id, j->version);
}
@ -340,7 +338,7 @@ static int job_on_exit(sd_event_source *s, const siginfo_t *si, void *userdata)
else {
r = job_parse_child_output(TAKE_FD(j->stdout_fd), &json);
if (r < 0)
sd_bus_error_set_errnof(&error, r, "Failed to parse JSON: %m");
sd_bus_error_set_errnof(&error, r, "Failed to parse job worker output: %m");
}
/* Only send notification of exit if the job was actually detached */
@ -355,17 +353,23 @@ static int job_on_exit(sd_event_source *s, const siginfo_t *si, void *userdata)
j->object_path,
j->status_errno != 0 ? -j->status_errno : si->si_status);
if (r < 0)
log_warning_errno(r, "Cannot emit JobRemoved message, ignoring: %m");
log_warning_errno(r,
"Cannot emit JobRemoved message for job %" PRIu64 ", ignoring: %m",
j->id);
}
if (j->dbus_msg && j->complete_cb) {
if (sd_bus_error_is_set(&error)) {
log_warning("Bus error occurred, ignoring callback for job: %s", error.message);
log_warning("Job %" PRIu64 " failed with bus error, ignoring callback: %s",
j->id, error.message);
sd_bus_reply_method_error(j->dbus_msg, &error);
} else {
r = j->complete_cb(j->dbus_msg, j, json, &error);
if (r < 0) {
log_warning_errno(r, "Error during execution of job callback: %s", bus_error_message(&error, r));
log_warning_errno(r,
"Error during execution of job callback for job %" PRIu64 ": %s",
j->id,
bus_error_message(&error, r));
sd_bus_reply_method_errno(j->dbus_msg, r, &error);
}
}
@ -510,6 +514,9 @@ static int job_start(Job *j) {
_exit(EXIT_FAILURE);
}
log_info("Started job %" PRIu64 " with worker PID " PID_FMT,
j->id, pid.pid);
r = event_add_child_pidref(j->manager->event, &j->child, &pid, WEXITED, job_on_exit, j);
if (r < 0)
return log_error_errno(r, "Failed to add child process to event loop: %m");
@ -1450,7 +1457,7 @@ static int manager_on_notify(sd_event_source *s, int fd, uint32_t revents, void
Manager *m = ASSERT_PTR(userdata);
Job *j;
ssize_t n;
char *p;
char *version, *progress, *errno_str, *ready;
n = recvmsg_safe(fd, &msghdr, MSG_DONTWAIT|MSG_CMSG_CLOEXEC);
if (n < 0) {
@ -1487,29 +1494,22 @@ static int manager_on_notify(sd_event_source *s, int fd, uint32_t revents, void
buf[n] = 0;
p = find_line_startswith(buf, "X_SYSUPDATE_VERSION=");
if (p) {
p = strdupcspn(p, "\n");
if (p)
job_on_version(j, p);
}
version = find_line_startswith(buf, "X_SYSUPDATE_VERSION=");
progress = find_line_startswith(buf, "X_SYSUPDATE_PROGRESS=");
errno_str = find_line_startswith(buf, "ERRNO=");
ready = find_line_startswith(buf, "READY=1");
p = find_line_startswith(buf, "ERRNO=");
if (p) {
p = strdupcspn(p, "\n");
if (p)
job_on_errno(j, p);
}
if (version)
job_on_version(j, truncate_nl(version));
p = find_line_startswith(buf, "X_SYSUPDATE_PROGRESS=");
if (p) {
p = strdupcspn(p, "\n");
if (p)
job_on_progress(j, p);
}
if (progress)
job_on_progress(j, truncate_nl(progress));
if (errno_str)
job_on_errno(j, truncate_nl(errno_str));
/* Should come last, since this might actually detach the job */
if (find_line_startswith(buf, "READY=1"))
if (ready)
job_on_ready(j);
return 0;