#include "mkdir.h"
#include "label.h"
#include "fileio-label.h"
+#include "bus-errors.h"
const UnitVTable * const unit_vtable[_UNIT_TYPE_MAX] = {
[UNIT_SERVICE] = &service_vtable,
}
void unit_notify(Unit *u, UnitActiveState os, UnitActiveState ns, bool reload_success) {
+ Manager *m;
bool unexpected;
assert(u);
* behavior here. For example: if a mount point is remounted
* this function will be called too! */
- if (u->manager->n_reloading <= 0) {
+ m = u->manager;
+
+ if (m->n_reloading <= 0) {
dual_timestamp ts;
dual_timestamp_get(&ts);
if (UNIT_IS_INACTIVE_OR_FAILED(ns))
cgroup_bonding_trim_list(u->cgroup_bondings, true);
+ 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 (UNIT_IS_INACTIVE_OR_FAILED(ns))
+ m->n_on_console--;
+ else
+ m->n_on_console++;
+ }
+ }
+
if (u->job) {
unexpected = false;
} else
unexpected = true;
- if (u->manager->n_reloading <= 0) {
+ if (m->n_reloading <= 0) {
/* If this state change happened without being
* requested by a job, then let's retroactively start
/* The bus just might have become available,
* hence try to connect to it, if we aren't
* yet connected. */
- bus_init(u->manager, true);
+ bus_init(m, true);
if (u->type == UNIT_SERVICE &&
!UNIT_IS_ACTIVE_OR_RELOADING(os) &&
- u->manager->n_reloading <= 0) {
+ m->n_reloading <= 0) {
/* Write audit record if we have just finished starting up */
- manager_send_unit_audit(u->manager, u, AUDIT_SERVICE_START, true);
+ manager_send_unit_audit(m, u, AUDIT_SERVICE_START, true);
u->in_audit = true;
}
if (!UNIT_IS_ACTIVE_OR_RELOADING(os))
- manager_send_unit_plymouth(u->manager, u);
+ manager_send_unit_plymouth(m, u);
} else {
if (u->type == UNIT_SERVICE &&
UNIT_IS_INACTIVE_OR_FAILED(ns) &&
!UNIT_IS_INACTIVE_OR_FAILED(os) &&
- u->manager->n_reloading <= 0) {
+ m->n_reloading <= 0) {
/* Hmm, if there was no start record written
* write it now, so that we always have a nice
* pair */
if (!u->in_audit) {
- manager_send_unit_audit(u->manager, u, AUDIT_SERVICE_START, ns == UNIT_INACTIVE);
+ manager_send_unit_audit(m, u, AUDIT_SERVICE_START, ns == UNIT_INACTIVE);
if (ns == UNIT_INACTIVE)
- manager_send_unit_audit(u->manager, u, AUDIT_SERVICE_STOP, true);
+ manager_send_unit_audit(m, u, AUDIT_SERVICE_STOP, true);
} else
/* Write audit record if we have just finished shutting down */
- manager_send_unit_audit(u->manager, u, AUDIT_SERVICE_STOP, ns == UNIT_INACTIVE);
+ manager_send_unit_audit(m, u, AUDIT_SERVICE_STOP, ns == UNIT_INACTIVE);
u->in_audit = false;
}
}
- manager_recheck_journal(u->manager);
+ manager_recheck_journal(m);
/* Maybe we finished startup and are now ready for being
* stopped because unneeded? */
- unit_check_unneeded(u);
+ if (u->manager->n_reloading <= 0)
+ unit_check_unneeded(u);
unit_add_to_dbus_queue(u);
unit_add_to_gc_queue(u);
job_free(j);
return r;
}
+
+ if (j->state == JOB_RUNNING)
+ u->manager->n_running_jobs++;
} else {
/* legacy */
JobType type = job_type_from_string(v);
return UNIT_VTABLE(u)->kill(u, w, signo, error);
}
+int unit_kill_common(Unit *u, KillWho who, int signo, pid_t main_pid, pid_t control_pid, DBusError *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));
+ else
+ dbus_set_error(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));
+ else
+ dbus_set_error(error, BUS_ERROR_NO_SUCH_PROCESS, "No control process to kill");
+ return -ESRCH;
+ }
+
+ if (who == KILL_CONTROL || who == KILL_ALL)
+ if (control_pid > 0)
+ if (kill(control_pid, signo) < 0)
+ r = -errno;
+
+ if (who == KILL_MAIN || who == KILL_ALL)
+ if (main_pid > 0)
+ if (kill(main_pid, signo) < 0)
+ r = -errno;
+
+ if (who == KILL_ALL) {
+ _cleanup_set_free_ Set *pid_set = NULL;
+ int q;
+
+ pid_set = set_new(trivial_hash_func, trivial_compare_func);
+ if (!pid_set)
+ return -ENOMEM;
+
+ /* Exclude the control/main pid from being killed via the cgroup */
+ if (control_pid > 0) {
+ q = set_put(pid_set, LONG_TO_PTR(control_pid));
+ if (q < 0)
+ return q;
+ }
+
+ if (main_pid > 0) {
+ q = set_put(pid_set, LONG_TO_PTR(main_pid));
+ if (q < 0)
+ return q;
+ }
+
+ q = cgroup_bonding_kill_list(u->cgroup_bondings, signo, false, false, pid_set, NULL);
+ if (q < 0 && q != -EAGAIN && q != -ESRCH && q != -ENOENT)
+ r = q;
+ }
+
+ return r;
+}
+
int unit_following_set(Unit *u, Set **s) {
assert(u);
assert(s);