Systemd/src/machine/operation.c
Lennart Poettering 0c69794138 tree-wide: remove Lennart's copyright lines
These lines are generally out-of-date, incomplete and unnecessary. With
SPDX and git repository much more accurate and fine grained information
about licensing and authorship is available, hence let's drop the
per-file copyright notice. Of course, removing copyright lines of others
is problematic, hence this commit only removes my own lines and leaves
all others untouched. It might be nicer if sooner or later those could
go away too, making git the only and accurate source of authorship
information.
2018-06-14 10:20:20 +02:00

139 lines
3.9 KiB
C

/* SPDX-License-Identifier: LGPL-2.1+ */
#include <sys/wait.h>
#include "alloc-util.h"
#include "fd-util.h"
#include "operation.h"
#include "process-util.h"
static int operation_done(sd_event_source *s, const siginfo_t *si, void *userdata) {
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
Operation *o = userdata;
int r;
assert(o);
assert(si);
log_debug("Operating " PID_FMT " is now complete with code=%s status=%i",
o->pid,
sigchld_code_to_string(si->si_code), si->si_status);
o->pid = 0;
if (si->si_code != CLD_EXITED) {
r = sd_bus_error_setf(&error, SD_BUS_ERROR_FAILED, "Child died abnormally.");
goto fail;
}
if (si->si_status == EXIT_SUCCESS)
r = 0;
else if (read(o->errno_fd, &r, sizeof(r)) != sizeof(r)) { /* Try to acquire error code for failed operation */
r = sd_bus_error_setf(&error, SD_BUS_ERROR_FAILED, "Child failed.");
goto fail;
}
if (o->done) {
/* A completion routine is set for this operation, call it. */
r = o->done(o, r, &error);
if (r < 0) {
if (!sd_bus_error_is_set(&error))
sd_bus_error_set_errno(&error, r);
goto fail;
}
} else {
/* The default operation when done is to simply return an error on failure or an empty success
* message on success. */
if (r < 0) {
sd_bus_error_set_errno(&error, r);
goto fail;
}
r = sd_bus_reply_method_return(o->message, NULL);
if (r < 0)
log_error_errno(r, "Failed to reply to message: %m");
}
operation_free(o);
return 0;
fail:
r = sd_bus_reply_method_error(o->message, &error);
if (r < 0)
log_error_errno(r, "Failed to reply to message: %m");
operation_free(o);
return 0;
}
int operation_new(Manager *manager, Machine *machine, pid_t child, sd_bus_message *message, int errno_fd, Operation **ret) {
Operation *o;
int r;
assert(manager);
assert(child > 1);
assert(message);
assert(errno_fd >= 0);
o = new0(Operation, 1);
if (!o)
return -ENOMEM;
o->extra_fd = -1;
r = sd_event_add_child(manager->event, &o->event_source, child, WEXITED, operation_done, o);
if (r < 0) {
free(o);
return r;
}
o->pid = child;
o->message = sd_bus_message_ref(message);
o->errno_fd = errno_fd;
LIST_PREPEND(operations, manager->operations, o);
manager->n_operations++;
o->manager = manager;
if (machine) {
LIST_PREPEND(operations_by_machine, machine->operations, o);
o->machine = machine;
}
log_debug("Started new operation " PID_FMT ".", child);
/* At this point we took ownership of both the child and the errno file descriptor! */
if (ret)
*ret = o;
return 0;
}
Operation *operation_free(Operation *o) {
if (!o)
return NULL;
sd_event_source_unref(o->event_source);
safe_close(o->errno_fd);
safe_close(o->extra_fd);
if (o->pid > 1)
(void) sigkill_wait(o->pid);
sd_bus_message_unref(o->message);
if (o->manager) {
LIST_REMOVE(operations, o->manager->operations, o);
o->manager->n_operations--;
}
if (o->machine)
LIST_REMOVE(operations_by_machine, o->machine->operations, o);
return mfree(o);
}