manager.c revision 8b55b8c4e7fce5e05dcfd783a37fb843d1bf1868
08bcebf36eb85f5e75b968de8c648e6614cc534bLennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
08bcebf36eb85f5e75b968de8c648e6614cc534bLennart Poettering This file is part of systemd.
08bcebf36eb85f5e75b968de8c648e6614cc534bLennart Poettering Copyright 2010 Lennart Poettering
08bcebf36eb85f5e75b968de8c648e6614cc534bLennart Poettering systemd is free software; you can redistribute it and/or modify it
08bcebf36eb85f5e75b968de8c648e6614cc534bLennart Poettering under the terms of the GNU Lesser General Public License as published by
08bcebf36eb85f5e75b968de8c648e6614cc534bLennart Poettering the Free Software Foundation; either version 2.1 of the License, or
08bcebf36eb85f5e75b968de8c648e6614cc534bLennart Poettering (at your option) any later version.
08bcebf36eb85f5e75b968de8c648e6614cc534bLennart Poettering systemd is distributed in the hope that it will be useful, but
08bcebf36eb85f5e75b968de8c648e6614cc534bLennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
08bcebf36eb85f5e75b968de8c648e6614cc534bLennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
08bcebf36eb85f5e75b968de8c648e6614cc534bLennart Poettering Lesser General Public License for more details.
08bcebf36eb85f5e75b968de8c648e6614cc534bLennart Poettering You should have received a copy of the GNU Lesser General Public License
08bcebf36eb85f5e75b968de8c648e6614cc534bLennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
08bcebf36eb85f5e75b968de8c648e6614cc534bLennart Poettering/* As soon as 16 units are in our GC queue, make sure to run a gc sweep */
08bcebf36eb85f5e75b968de8c648e6614cc534bLennart Poettering/* As soon as 5s passed since a unit was added to our GC queue, make sure to run a gc sweep */
08bcebf36eb85f5e75b968de8c648e6614cc534bLennart Poettering#define GC_QUEUE_USEC_MAX (10*USEC_PER_SEC)
08bcebf36eb85f5e75b968de8c648e6614cc534bLennart Poettering/* Where clients shall send notification messages to */
08bcebf36eb85f5e75b968de8c648e6614cc534bLennart Poettering#define NOTIFY_SOCKET "@/org/freedesktop/systemd1/notify"
} sa;
assert(m);
return -errno;
if (bind(m->notify_watch.fd, &sa.sa, offsetof(struct sockaddr_un, sun_path) + 1 + strlen(sa.un.sun_path+1)) < 0) {
return -errno;
return -errno;
return -errno;
if (!m->notify_socket)
return log_oom();
assert(m);
return -errno;
if (timerfd_settime(m->time_change_watch.fd, TFD_TIMER_ABSTIME|TFD_TIMER_CANCEL_ON_SET, &its, NULL) < 0) {
return -errno;
int fd;
assert(m);
if (fd < 0) {
assert(m);
return -errno;
return -errno;
return enable_special_signals(m);
assert(m);
Manager *m;
int r = -ENOMEM;
return -ENOMEM;
if (!m->environment)
goto fail;
if (!m->default_controllers)
goto fail;
goto fail;
goto fail;
goto fail;
goto fail;
goto fail;
if (m->epoll_fd < 0)
goto fail;
r = manager_setup_signals(m);
goto fail;
r = manager_setup_cgroup(m);
goto fail;
r = manager_setup_notify(m);
goto fail;
r = manager_setup_time_change(m);
goto fail;
goto fail;
*_m = m;
fail:
manager_free(m);
Unit *u;
assert(m);
while ((u = m->cleanup_queue)) {
unit_free(u);
Iterator i;
bool is_bad;
assert(u);
if (u->in_cleanup_queue)
goto bad;
if (unit_check_gc(u))
goto good;
is_bad = true;
goto good;
is_bad = false;
if (is_bad)
goto bad;
bad:
good:
Unit *u;
unsigned gc_marker;
assert(m);
(m->gc_queue_timestamp <= 0 ||
while ((u = m->gc_queue)) {
u->in_gc_queue = false;
m->n_in_gc_queue = 0;
m->gc_queue_timestamp = 0;
Unit *u;
assert(m);
unit_free(u);
UnitType c;
assert(m);
for (c = 0; c < _UNIT_TYPE_MAX; c++)
bus_done(m);
if (m->epoll_fd >= 0)
for (i = 0; i < RLIMIT_NLIMITS; i++)
free(m);
UnitType c;
assert(m);
for (c = 0; c < _UNIT_TYPE_MAX; c++)
Iterator i;
Unit *u;
assert(m);
if (u->id != k)
if ((q = unit_coldplug(u)) < 0)
assert(m);
if (!m->unit_path_cache) {
d = opendir(*i);
r = -ENOMEM;
goto fail;
free(p);
goto fail;
closedir(d);
d = NULL;
fail:
assert(m);
r = lookup_paths_init(
if (serialization)
m->n_reloading ++;
r = manager_enumerate(m);
if (serialization) {
q = manager_coldplug(m);
if (serialization) {
m->n_reloading --;
int manager_add_job(Manager *m, JobType type, Unit *unit, JobMode mode, bool override, DBusError *e, Job **_ret) {
assert(m);
return -EINVAL;
return -EPERM;
if (!tr)
return -ENOMEM;
goto tr_abort;
goto tr_abort;
goto tr_abort;
if (_ret)
int manager_add_job_by_name(Manager *m, JobType type, const char *name, JobMode mode, bool override, DBusError *e, Job **_ret) {
assert(m);
assert(m);
assert(m);
Unit *u;
assert(m);
if (m->dispatching_load_queue)
m->dispatching_load_queue = true;
while ((u = m->load_queue)) {
unit_load(u);
m->dispatching_load_queue = false;
int manager_load_unit_prepare(Manager *m, const char *name, const char *path, DBusError *e, Unit **_ret) {
UnitType t;
assert(m);
return -EINVAL;
if (!name)
return -EINVAL;
if (ret) {
if (!ret)
return -ENOMEM;
if (path) {
return -ENOMEM;
if (_ret)
assert(m);
if (_ret)
Iterator i;
Job *j;
assert(s);
assert(f);
Iterator i;
Unit *u;
assert(s);
assert(f);
if (u->id == t)
Job *j;
assert(m);
Job *j;
if (m->dispatching_run_queue)
m->dispatching_run_queue = true;
while ((j = m->run_queue)) {
m->dispatching_run_queue = false;
Job *j;
Unit *u;
assert(m);
if (m->dispatching_dbus_queue)
m->dispatching_dbus_queue = true;
while ((u = m->dbus_unit_queue)) {
while ((j = m->dbus_job_queue)) {
m->dispatching_dbus_queue = false;
ssize_t n;
assert(m);
} control;
Unit *u;
char **tags;
return -EIO;
return -errno;
buf[n] = 0;
if (!tags)
return log_oom();
assert(m);
Unit *u;
return -errno;
r = manager_process_notify_fd(m);
return -errno;
ssize_t n;
bool sigchld = false;
assert(m);
if (n != sizeof(sfsi)) {
return -EIO;
return -errno;
char *p = NULL;
free(p);
case SIGCHLD:
sigchld = true;
case SIGTERM:
case SIGINT:
case SIGWINCH:
case SIGPWR:
case SIGUSR1: {
Unit *u;
bus_init(m, true);
case SIGUSR2: {
FILE *f;
if (ferror(f)) {
fclose(f);
fclose(f);
case SIGHUP:
static const char * const target_table[] = {
[0] = SPECIAL_DEFAULT_TARGET,
[0] = MANAGER_HALT,
manager_set_show_status(m, true);
manager_set_show_status(m, false);
if (sigchld)
return manager_dispatch_sigchld(m);
Watch *w;
assert(m);
switch (w->type) {
case WATCH_SIGNAL:
return -EINVAL;
if ((r = manager_process_signal_fd(m)) < 0)
case WATCH_NOTIFY:
return -EINVAL;
if ((r = manager_process_notify_fd(m)) < 0)
case WATCH_FD:
case WATCH_UNIT_TIMER:
case WATCH_JOB_TIMER: {
uint64_t v;
ssize_t k;
case WATCH_MOUNT:
case WATCH_SWAP:
case WATCH_UDEV:
case WATCH_DBUS_WATCH:
case WATCH_DBUS_TIMEOUT:
case WATCH_TIME_CHANGE: {
Unit *u;
Iterator i;
NULL);
assert(m);
r = manager_dispatch_sigchld(m);
if (manager_dispatch_load_queue(m) > 0)
if (manager_dispatch_run_queue(m) > 0)
if (bus_dispatch(m) > 0)
if (manager_dispatch_cleanup_queue(m) > 0)
if (manager_dispatch_gc_queue(m) > 0)
if (manager_dispatch_dbus_queue(m) > 0)
if (swap_dispatch_reload(m) > 0)
if (wait_msec <= 0)
return -errno;
return m->exit_code;
Unit *u;
assert(m);
assert(s);
return -EINVAL;
return -ENOMEM;
free(n);
*_u = u;
Job *j;
unsigned id;
assert(m);
assert(s);
return -EINVAL;
return -ENOENT;
*_j = j;
#ifdef HAVE_AUDIT
int audit_fd;
if (audit_fd < 0)
if (m->n_reloading > 0)
free(p);
if (m->n_reloading > 0)
if (connect(fd, &sa.sa, offsetof(struct sockaddr_un, sun_path) + 1 + strlen(sa.un.sun_path+1)) < 0) {
goto finish;
log_oom();
goto finish;
errno = 0;
goto finish;
if (fd >= 0)
Manager *m,
const char *name,
const char* old_owner,
const char *new_owner) {
Unit *u;
assert(m);
Manager *m,
const char *name,
Unit *u;
assert(m);
int fd;
FILE *f;
if (!path)
return -ENOMEM;
if (fd < 0) {
return -errno;
return -errno;
*_f = f;
Iterator i;
Unit *u;
assert(m);
assert(f);
m->n_reloading ++;
if (!in_initrd()) {
if (u->id != t)
if (!unit_can_serialize(u))
m->n_reloading --;
m->n_reloading --;
if (ferror(f))
return -EIO;
assert(m);
assert(f);
m->n_reloading ++;
if (feof(f))
r = -errno;
goto finish;
uint32_t n;
m->n_installed_jobs += n;
uint32_t n;
m->n_failed_jobs += n;
Unit *u;
if (feof(f))
r = -errno;
goto finish;
goto finish;
goto finish;
if (ferror(f)) {
r = -EIO;
goto finish;
m->n_reloading --;
Unit *u;
Iterator i;
assert(m);
FILE *f;
assert(m);
r = manager_open_serialization(m, &f);
m->n_reloading ++;
if (!fds) {
m->n_reloading --;
r = -ENOMEM;
goto finish;
m->n_reloading --;
goto finish;
m->n_reloading --;
r = -errno;
goto finish;
q = lookup_paths_init(
q = manager_enumerate(m);
fclose(f);
f = NULL;
q = manager_coldplug(m);
m->n_reloading--;
fclose(f);
if (fds)
Unit *u;
assert(m);
return !!u->job;
Unit *u;
Iterator i;
assert(m);
Unit *u;
assert(m);
return unit_pending_inactive(u);
char userspace[FORMAT_TIMESPAN_MAX], initrd[FORMAT_TIMESPAN_MAX], kernel[FORMAT_TIMESPAN_MAX], sum[FORMAT_TIMESPAN_MAX];
assert(m);
m->confirm_spawn = false;
if (!log_on_console())
NULL);
initrd_usec = 0;
if (!log_on_console())
NULL);
if (!log_on_console())
NULL);
bus_broadcast_finished(m, firmware_usec, loader_usec, kernel_usec, initrd_usec, userspace_usec, total_usec);
sd_notifyf(false,
assert(m);
if (*generator)
return log_oom();
p, strerror(-r));
free(p);
return log_oom();
if (!mkdtemp(p)) {
free(p);
return -errno;
*generator = p;
assert(m);
if (!*generator)
const char *generator_path;
mode_t u;
assert(m);
goto finish;
goto finish;
goto finish;
umask(u);
closedir(d);
assert(m);
if (!*generator)
assert(m);
assert(m);
return -ENOMEM;
m->default_controllers = l;
assert(m);
for (i = 0; i < RLIMIT_NLIMITS; i++) {
if (!default_rlimit[i])
if (!m->rlimit[i])
return -ENOMEM;
Unit *u;
assert(m);
log_open();
assert(m);
m->show_status = b;
assert(m);
if (m->show_status)
return plymouth_running();
assert(w);