#include <unistd.h>
#include <sys/stat.h>
-#include "systemd/sd-id128.h"
-#include "systemd/sd-messages.h"
+#include "sd-id128.h"
+#include "sd-messages.h"
#include "set.h"
#include "unit.h"
#include "macro.h"
#include "label.h"
#include "fileio-label.h"
#include "bus-errors.h"
+#include "dbus.h"
const UnitVTable * const unit_vtable[_UNIT_TYPE_MAX] = {
[UNIT_SERVICE] = &service_vtable,
goto fail;
}
- if ((r = unit_name_to_instance(s, &i)) < 0)
+ r = unit_name_to_instance(s, &i);
+ if (r < 0)
goto fail;
if (i && unit_vtable[t]->no_instances) {
goto fail;
}
- if ((r = set_put(u->names, s)) < 0) {
+ r = set_put(u->names, s);
+ if (r < 0) {
if (r == -EEXIST)
r = 0;
goto fail;
}
- if ((r = hashmap_put(u->manager->units, s, u)) < 0) {
+ r = hashmap_put(u->manager->units, s, u);
+ if (r < 0) {
set_remove(u->names, s);
goto fail;
}
if (!u->instance)
return -EINVAL;
- if (!(t = unit_name_replace_instance(name, u->instance)))
+ t = unit_name_replace_instance(name, u->instance);
+ if (!t)
return -ENOMEM;
name = t;
if (!s)
return -ENOENT;
- if ((r = unit_name_to_instance(s, &i)) < 0)
+ r = unit_name_to_instance(s, &i);
+ if (r < 0)
return r;
u->id = s;
return;
/* Shortcut things if nobody cares */
- if (!bus_has_subscriber(u->manager)) {
+ if (set_isempty(u->manager->subscribed)) {
u->sent_dbus_new_signal = true;
return;
}
SET_FOREACH(back, other->dependencies[d], i) {
UnitDependency k;
- for (k = 0; k < _UNIT_DEPENDENCY_MAX; k++)
- if ((r = set_remove_and_put(back->dependencies[k], other, u)) < 0) {
-
- if (r == -EEXIST)
- set_remove(back->dependencies[k], other);
- else
- assert(r == -ENOENT);
- }
+ for (k = 0; k < _UNIT_DEPENDENCY_MAX; k++) {
+ r = set_remove_and_put(back->dependencies[k], other, u);
+ if (r == -EEXIST)
+ set_remove(back->dependencies[k], other);
+ else
+ assert(r >= 0 || r == -ENOENT);
+ }
}
complete_move(&u->dependencies[d], &other->dependencies[d]);
if (!u->instance)
return -EINVAL;
- if (!(s = unit_name_replace_instance(name, u->instance)))
+ s = unit_name_replace_instance(name, u->instance);
+ if (!s)
return -ENOMEM;
name = s;
assert(u);
- /* Load a .service file */
+ /* Load a .{service,socket,...} file */
r = unit_load_fragment(u);
if (r < 0)
return r;
if (state != UNIT_ACTIVE)
return -ENOEXEC;
- if ((following = unit_following(u))) {
+ following = unit_following(u);
+ if (following) {
log_debug_unit(u->id, "Redirecting reload request from %s to %s.",
u->id, following->id);
return unit_reload(following);
if (UNIT_IS_INACTIVE_OR_FAILED(ns))
unit_destroy_cgroup(u);
+ /* Note that this doesn't apply to RemainAfterExit services exiting
+ * sucessfully, since there's no change of state in that case. Which is
+ * why it is handled in service_set_state() */
if (UNIT_IS_INACTIVE_OR_FAILED(os) != UNIT_IS_INACTIVE_OR_FAILED(ns)) {
ExecContext *ec = unit_get_exec_context(u);
if (ec && exec_context_may_touch_console(ec)) {
if (m->n_on_console == 0)
/* unset no_console_output flag, since the console is free */
- m->no_console_output = 0;
+ m->no_console_output = false;
} else
m->n_on_console ++;
}
unit_add_to_gc_queue(u);
}
-int unit_watch_fd(Unit *u, int fd, uint32_t events, Watch *w) {
- struct epoll_event ev = {
- .data.ptr = w,
- .events = events,
- };
-
- assert(u);
- assert(fd >= 0);
- assert(w);
- assert(w->type == WATCH_INVALID || (w->type == WATCH_FD && w->fd == fd && w->data.unit == u));
-
- if (epoll_ctl(u->manager->epoll_fd,
- w->type == WATCH_INVALID ? EPOLL_CTL_ADD : EPOLL_CTL_MOD,
- fd,
- &ev) < 0)
- return -errno;
-
- w->fd = fd;
- w->type = WATCH_FD;
- w->data.unit = u;
-
- return 0;
-}
-
-void unit_unwatch_fd(Unit *u, Watch *w) {
- assert(u);
- assert(w);
-
- if (w->type == WATCH_INVALID)
- return;
-
- assert(w->type == WATCH_FD);
- assert(w->data.unit == u);
- assert_se(epoll_ctl(u->manager->epoll_fd, EPOLL_CTL_DEL, w->fd, NULL) >= 0);
-
- w->fd = -1;
- w->type = WATCH_INVALID;
- w->data.unit = NULL;
-}
-
int unit_watch_pid(Unit *u, pid_t pid) {
assert(u);
assert(pid >= 1);
hashmap_remove_value(u->manager->watch_pids, LONG_TO_PTR(pid), u);
}
-int unit_watch_timer(Unit *u, clockid_t clock_id, bool relative, usec_t usec, Watch *w) {
- struct itimerspec its = {};
- int flags, fd;
- bool ours;
-
- assert(u);
- assert(w);
- assert(w->type == WATCH_INVALID || (w->type == WATCH_UNIT_TIMER && w->data.unit == u));
-
- /* This will try to reuse the old timer if there is one */
-
- if (w->type == WATCH_UNIT_TIMER) {
- assert(w->data.unit == u);
- assert(w->fd >= 0);
-
- ours = false;
- fd = w->fd;
- } else if (w->type == WATCH_INVALID) {
-
- ours = true;
- fd = timerfd_create(clock_id, TFD_NONBLOCK|TFD_CLOEXEC);
- if (fd < 0)
- return -errno;
- } else
- assert_not_reached("Invalid watch type");
-
- if (usec <= 0) {
- /* Set absolute time in the past, but not 0, since we
- * don't want to disarm the timer */
- its.it_value.tv_sec = 0;
- its.it_value.tv_nsec = 1;
-
- flags = TFD_TIMER_ABSTIME;
- } else {
- timespec_store(&its.it_value, usec);
- flags = relative ? 0 : TFD_TIMER_ABSTIME;
- }
-
- /* This will also flush the elapse counter */
- if (timerfd_settime(fd, flags, &its, NULL) < 0)
- goto fail;
-
- if (w->type == WATCH_INVALID) {
- struct epoll_event ev = {
- .data.ptr = w,
- .events = EPOLLIN,
- };
-
- if (epoll_ctl(u->manager->epoll_fd, EPOLL_CTL_ADD, fd, &ev) < 0)
- goto fail;
- }
-
- w->type = WATCH_UNIT_TIMER;
- w->fd = fd;
- w->data.unit = u;
-
- return 0;
-
-fail:
- if (ours)
- close_nointr_nofail(fd);
-
- return -errno;
-}
-
-void unit_unwatch_timer(Unit *u, Watch *w) {
- assert(u);
- assert(w);
-
- if (w->type == WATCH_INVALID)
- return;
-
- assert(w->type == WATCH_UNIT_TIMER);
- assert(w->data.unit == u);
- assert(w->fd >= 0);
-
- assert_se(epoll_ctl(u->manager->epoll_fd, EPOLL_CTL_DEL, w->fd, NULL) >= 0);
- close_nointr_nofail(w->fd);
-
- w->fd = -1;
- w->type = WATCH_INVALID;
- w->data.unit = NULL;
-}
-
bool unit_job_is_applicable(Unit *u, JobType j) {
assert(u);
assert(j >= 0 && j < _JOB_TYPE_MAX);
return false;
}
-int unit_kill(Unit *u, KillWho w, int signo, DBusError *error) {
+int unit_kill(Unit *u, KillWho w, int signo, sd_bus_error *error) {
assert(u);
assert(w >= 0 && w < _KILL_WHO_MAX);
assert(signo > 0);
int signo,
pid_t main_pid,
pid_t control_pid,
- DBusError *error) {
+ sd_bus_error *error) {
int r = 0;
if (who == KILL_MAIN && main_pid <= 0) {
if (main_pid < 0)
- dbus_set_error(error, BUS_ERROR_NO_SUCH_PROCESS, "%s units have no main processes", unit_type_to_string(u->type));
+ sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_PROCESS, "%s units have no main processes", unit_type_to_string(u->type));
else
- dbus_set_error(error, BUS_ERROR_NO_SUCH_PROCESS, "No main process to kill");
+ sd_bus_error_set_const(error, BUS_ERROR_NO_SUCH_PROCESS, "No main process to kill");
return -ESRCH;
}
if (who == KILL_CONTROL && control_pid <= 0) {
if (control_pid < 0)
- dbus_set_error(error, BUS_ERROR_NO_SUCH_PROCESS, "%s units have no control processes", unit_type_to_string(u->type));
+ sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_PROCESS, "%s units have no control processes", unit_type_to_string(u->type));
else
- dbus_set_error(error, BUS_ERROR_NO_SUCH_PROCESS, "No control process to kill");
+ sd_bus_error_set_const(error, BUS_ERROR_NO_SUCH_PROCESS, "No control process to kill");
return -ESRCH;
}
return (ExecContext*) ((uint8_t*) u + offset);
}
+KillContext *unit_get_kill_context(Unit *u) {
+ size_t offset;
+ assert(u);
+
+ offset = UNIT_VTABLE(u)->kill_context_offset;
+ if (offset <= 0)
+ return NULL;
+
+ return (KillContext*) ((uint8_t*) u + offset);
+}
+
CGroupContext *unit_get_cgroup_context(Unit *u) {
size_t offset;