#include "bus-util.h"
#include "bus-error.h"
#include "logind.h"
+#include "udev-util.h"
Manager *manager_new(void) {
Manager *m;
m->n_autovts = 6;
m->reserve_vt = 6;
+ m->remove_ipc = true;
m->inhibit_delay_max = 5 * USEC_PER_SEC;
m->handle_power_key = HANDLE_POWEROFF;
m->handle_suspend_key = HANDLE_SUSPEND;
m->idle_action = HANDLE_IGNORE;
m->idle_action_not_before_usec = now(CLOCK_MONOTONIC);
+ m->runtime_dir_size = PAGE_ALIGN((size_t) (physical_memory() / 10)); /* 10% */
+
m->devices = hashmap_new(string_hash_func, string_compare_func);
m->seats = hashmap_new(string_hash_func, string_compare_func);
m->sessions = hashmap_new(string_hash_func, string_compare_func);
m->busnames = set_new(string_hash_func, string_compare_func);
if (!m->devices || !m->seats || !m->sessions || !m->users || !m->inhibitors || !m->buttons || !m->busnames ||
- !m->user_units || !m->session_units ||
- !m->busnames) {
- manager_free(m);
- return NULL;
- }
+ !m->user_units || !m->session_units)
+ goto fail;
m->kill_exclude_users = strv_new("root", NULL);
- if (!m->kill_exclude_users) {
- manager_free(m);
- return NULL;
- }
+ if (!m->kill_exclude_users)
+ goto fail;
m->udev = udev_new();
- if (!m->udev) {
- manager_free(m);
- return NULL;
- }
+ if (!m->udev)
+ goto fail;
r = sd_event_default(&m->event);
- if (r < 0) {
- manager_free(m);
- return NULL;
- }
+ if (r < 0)
+ goto fail;
sd_event_set_watchdog(m->event, true);
return m;
+
+fail:
+ manager_free(m);
+ return NULL;
}
void manager_free(Manager *m) {
sd_event_source_unref(m->udev_device_event_source);
sd_event_source_unref(m->udev_vcsa_event_source);
sd_event_source_unref(m->udev_button_event_source);
+ sd_event_source_unref(m->lid_switch_ignore_event_source);
- if (m->console_active_fd >= 0)
- close_nointr_nofail(m->console_active_fd);
+ safe_close(m->console_active_fd);
if (m->udev_seat_monitor)
udev_monitor_unref(m->udev_seat_monitor);
sd_bus_unref(m->bus);
sd_event_unref(m->event);
- if (m->reserve_vt_fd >= 0)
- close_nointr_nofail(m->reserve_vt_fd);
+ safe_close(m->reserve_vt_fd);
strv_free(m->kill_only_users);
strv_free(m->kill_exclude_users);
static int manager_enumerate_devices(Manager *m) {
struct udev_list_entry *item = NULL, *first = NULL;
- struct udev_enumerate *e;
+ _cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL;
int r;
assert(m);
* necessary */
e = udev_enumerate_new(m->udev);
- if (!e) {
- r = -ENOMEM;
- goto finish;
- }
+ if (!e)
+ return -ENOMEM;
r = udev_enumerate_add_match_tag(e, "master-of-seat");
if (r < 0)
- goto finish;
+ return r;
+
+ r = udev_enumerate_add_match_is_initialized(e);
+ if (r < 0)
+ return r;
r = udev_enumerate_scan_devices(e);
if (r < 0)
- goto finish;
+ return r;
first = udev_enumerate_get_list_entry(e);
udev_list_entry_foreach(item, first) {
- struct udev_device *d;
+ _cleanup_udev_device_unref_ struct udev_device *d = NULL;
int k;
d = udev_device_new_from_syspath(m->udev, udev_list_entry_get_name(item));
- if (!d) {
- r = -ENOMEM;
- goto finish;
- }
+ if (!d)
+ return -ENOMEM;
k = manager_process_seat_device(m, d);
- udev_device_unref(d);
-
if (k < 0)
r = k;
}
-finish:
- if (e)
- udev_enumerate_unref(e);
-
return r;
}
static int manager_enumerate_buttons(Manager *m) {
+ _cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL;
struct udev_list_entry *item = NULL, *first = NULL;
- struct udev_enumerate *e;
int r;
assert(m);
return 0;
e = udev_enumerate_new(m->udev);
- if (!e) {
- r = -ENOMEM;
- goto finish;
- }
+ if (!e)
+ return -ENOMEM;
r = udev_enumerate_add_match_subsystem(e, "input");
if (r < 0)
- goto finish;
+ return r;
r = udev_enumerate_add_match_tag(e, "power-switch");
if (r < 0)
- goto finish;
+ return r;
+
+ r = udev_enumerate_add_match_is_initialized(e);
+ if (r < 0)
+ return r;
r = udev_enumerate_scan_devices(e);
if (r < 0)
- goto finish;
+ return r;
first = udev_enumerate_get_list_entry(e);
udev_list_entry_foreach(item, first) {
- struct udev_device *d;
+ _cleanup_udev_device_unref_ struct udev_device *d = NULL;
int k;
d = udev_device_new_from_syspath(m->udev, udev_list_entry_get_name(item));
- if (!d) {
- r = -ENOMEM;
- goto finish;
- }
+ if (!d)
+ return -ENOMEM;
k = manager_process_button_device(m, d);
- udev_device_unref(d);
-
if (k < 0)
r = k;
}
-finish:
- if (e)
- udev_enumerate_unref(e);
-
return r;
}
}
static int manager_dispatch_seat_udev(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
+ _cleanup_udev_device_unref_ struct udev_device *d = NULL;
Manager *m = userdata;
- struct udev_device *d;
- int r;
assert(m);
if (!d)
return -ENOMEM;
- r = manager_process_seat_device(m, d);
- udev_device_unref(d);
-
- return r;
+ manager_process_seat_device(m, d);
+ return 0;
}
static int manager_dispatch_device_udev(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
+ _cleanup_udev_device_unref_ struct udev_device *d = NULL;
Manager *m = userdata;
- struct udev_device *d;
- int r;
assert(m);
if (!d)
return -ENOMEM;
- r = manager_process_seat_device(m, d);
- udev_device_unref(d);
-
- return r;
+ manager_process_seat_device(m, d);
+ return 0;
}
static int manager_dispatch_vcsa_udev(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
+ _cleanup_udev_device_unref_ struct udev_device *d = NULL;
Manager *m = userdata;
- struct udev_device *d;
- int r = 0;
const char *name;
assert(m);
* VTs, to make sure our auto VTs never go away. */
if (name && startswith(name, "vcsa") && streq_ptr(udev_device_get_action(d), "remove"))
- r = seat_preallocate_vts(m->seat0);
-
- udev_device_unref(d);
+ seat_preallocate_vts(m->seat0);
- return r;
+ return 0;
}
static int manager_dispatch_button_udev(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
+ _cleanup_udev_device_unref_ struct udev_device *d = NULL;
Manager *m = userdata;
- struct udev_device *d;
- int r;
assert(m);
if (!d)
return -ENOMEM;
- r = manager_process_button_device(m, d);
- udev_device_unref(d);
-
- return r;
+ manager_process_button_device(m, d);
+ return 0;
}
static int manager_dispatch_console(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
assert(m->console_active_fd == fd);
seat_read_active_vt(m->seat0);
-
return 0;
}
return r;
}
- r = sd_bus_add_object_vtable(m->bus, "/org/freedesktop/login1", "org.freedesktop.login1.Manager", manager_vtable, m);
+ r = sd_bus_add_object_vtable(m->bus, NULL, "/org/freedesktop/login1", "org.freedesktop.login1.Manager", manager_vtable, m);
if (r < 0) {
log_error("Failed to add manager object vtable: %s", strerror(-r));
return r;
}
- r = sd_bus_add_fallback_vtable(m->bus, "/org/freedesktop/login1/seat", "org.freedesktop.login1.Seat", seat_vtable, seat_object_find, m);
+ r = sd_bus_add_fallback_vtable(m->bus, NULL, "/org/freedesktop/login1/seat", "org.freedesktop.login1.Seat", seat_vtable, seat_object_find, m);
if (r < 0) {
log_error("Failed to add seat object vtable: %s", strerror(-r));
return r;
}
- r = sd_bus_add_node_enumerator(m->bus, "/org/freedesktop/login1/seat", seat_node_enumerator, m);
+ r = sd_bus_add_node_enumerator(m->bus, NULL, "/org/freedesktop/login1/seat", seat_node_enumerator, m);
if (r < 0) {
log_error("Failed to add seat enumerator: %s", strerror(-r));
return r;
}
- r = sd_bus_add_fallback_vtable(m->bus, "/org/freedesktop/login1/session", "org.freedesktop.login1.Session", session_vtable, session_object_find, m);
+ r = sd_bus_add_fallback_vtable(m->bus, NULL, "/org/freedesktop/login1/session", "org.freedesktop.login1.Session", session_vtable, session_object_find, m);
if (r < 0) {
log_error("Failed to add session object vtable: %s", strerror(-r));
return r;
}
- r = sd_bus_add_node_enumerator(m->bus, "/org/freedesktop/login1/session", session_node_enumerator, m);
+ r = sd_bus_add_node_enumerator(m->bus, NULL, "/org/freedesktop/login1/session", session_node_enumerator, m);
if (r < 0) {
log_error("Failed to add session enumerator: %s", strerror(-r));
return r;
}
- r = sd_bus_add_fallback_vtable(m->bus, "/org/freedesktop/login1/user", "org.freedesktop.login1.User", user_vtable, user_object_find, m);
+ r = sd_bus_add_fallback_vtable(m->bus, NULL, "/org/freedesktop/login1/user", "org.freedesktop.login1.User", user_vtable, user_object_find, m);
if (r < 0) {
log_error("Failed to add user object vtable: %s", strerror(-r));
return r;
}
- r = sd_bus_add_node_enumerator(m->bus, "/org/freedesktop/login1/user", user_node_enumerator, m);
+ r = sd_bus_add_node_enumerator(m->bus, NULL, "/org/freedesktop/login1/user", user_node_enumerator, m);
if (r < 0) {
log_error("Failed to add user enumerator: %s", strerror(-r));
return r;
}
r = sd_bus_add_match(m->bus,
+ NULL,
"type='signal',"
"sender='org.freedesktop.DBus',"
"interface='org.freedesktop.DBus',"
}
r = sd_bus_add_match(m->bus,
+ NULL,
"type='signal',"
"sender='org.freedesktop.systemd1',"
"interface='org.freedesktop.systemd1.Manager',"
}
r = sd_bus_add_match(m->bus,
+ NULL,
"type='signal',"
"sender='org.freedesktop.systemd1',"
"interface='org.freedesktop.systemd1.Manager',"
}
r = sd_bus_add_match(m->bus,
+ NULL,
"type='signal',"
"sender='org.freedesktop.systemd1',"
"interface='org.freedesktop.DBus.Properties',"
}
r = sd_bus_add_match(m->bus,
+ NULL,
"type='signal',"
"sender='org.freedesktop.systemd1',"
"interface='org.freedesktop.systemd1.Manager',"
return -errno;
}
- r = sd_event_add_io(m->event, m->console_active_fd, 0, manager_dispatch_console, m, &m->console_active_event_source);
+ r = sd_event_add_io(m->event, &m->console_active_event_source, m->console_active_fd, 0, manager_dispatch_console, m);
if (r < 0) {
log_error("Failed to watch foreground console");
return r;
if (r < 0)
return r;
- r = sd_event_add_io(m->event, udev_monitor_get_fd(m->udev_seat_monitor), EPOLLIN, manager_dispatch_seat_udev, m, &m->udev_seat_event_source);
+ r = sd_event_add_io(m->event, &m->udev_seat_event_source, udev_monitor_get_fd(m->udev_seat_monitor), EPOLLIN, manager_dispatch_seat_udev, m);
if (r < 0)
return r;
if (r < 0)
return r;
- r = sd_event_add_io(m->event, udev_monitor_get_fd(m->udev_device_monitor), EPOLLIN, manager_dispatch_device_udev, m, &m->udev_device_event_source);
+ r = sd_event_add_io(m->event, &m->udev_device_event_source, udev_monitor_get_fd(m->udev_device_monitor), EPOLLIN, manager_dispatch_device_udev, m);
if (r < 0)
return r;
if (r < 0)
return r;
- r = sd_event_add_io(m->event, udev_monitor_get_fd(m->udev_button_monitor), EPOLLIN, manager_dispatch_button_udev, m, &m->udev_button_event_source);
+ r = sd_event_add_io(m->event, &m->udev_button_event_source, udev_monitor_get_fd(m->udev_button_monitor), EPOLLIN, manager_dispatch_button_udev, m);
if (r < 0)
return r;
}
if (r < 0)
return r;
- r = sd_event_add_io(m->event, udev_monitor_get_fd(m->udev_vcsa_monitor), EPOLLIN, manager_dispatch_vcsa_udev, m, &m->udev_vcsa_event_source);
+ r = sd_event_add_io(m->event, &m->udev_vcsa_event_source, udev_monitor_get_fd(m->udev_vcsa_monitor), EPOLLIN, manager_dispatch_vcsa_udev, m);
if (r < 0)
return r;
}
seat->in_gc_queue = false;
if (!seat_check_gc(seat, drop_not_started)) {
- seat_stop(seat);
+ seat_stop(seat, false);
seat_free(seat);
}
}
LIST_REMOVE(gc_queue, m->session_gc_queue, session);
session->in_gc_queue = false;
+ /* First, if we are not closing yet, initiate stopping */
+ if (!session_check_gc(session, drop_not_started) &&
+ session_get_state(session) != SESSION_CLOSING)
+ session_stop(session, false);
+
+ /* Normally, this should make the session busy again,
+ * if it doesn't then let's get rid of it
+ * immediately */
if (!session_check_gc(session, drop_not_started)) {
- session_stop(session);
session_finalize(session);
session_free(session);
}
LIST_REMOVE(gc_queue, m->user_gc_queue, user);
user->in_gc_queue = false;
+ /* First step: queue stop jobs */
+ if (!user_check_gc(user, drop_not_started))
+ user_stop(user, false);
+
+ /* Second step: finalize user */
if (!user_check_gc(user, drop_not_started)) {
- user_stop(user);
user_finalize(user);
user_free(user);
}
if (!m->idle_action_event_source) {
- r = sd_event_add_monotonic(m->event, elapse, USEC_PER_SEC*30, manager_dispatch_idle_action, m, &m->idle_action_event_source);
+ r = sd_event_add_time(
+ m->event,
+ &m->idle_action_event_source,
+ CLOCK_MONOTONIC,
+ elapse, USEC_PER_SEC*30,
+ manager_dispatch_idle_action, m);
if (r < 0) {
log_error("Failed to add idle event source: %s", strerror(-r));
return r;
Seat *seat;
Session *session;
User *user;
+ Button *button;
Inhibitor *inhibitor;
Iterator i;
return r;
}
+ r = manager_set_lid_switch_ignore(m, 0 + IGNORE_LID_SWITCH_STARTUP_USEC);
+ if (r < 0)
+ log_warning("Failed to set up lid switch ignore event source: %s", strerror(-r));
+
/* Deserialize state */
r = manager_enumerate_devices(m);
if (r < 0)
HASHMAP_FOREACH(inhibitor, m->inhibitors, i)
inhibitor_start(inhibitor);
+ HASHMAP_FOREACH(button, m->buttons, i)
+ button_check_switches(button);
+
manager_dispatch_idle_action(NULL, 0, m);
return 0;
}
-static int manager_recheck_buttons(Manager *m) {
- Iterator i;
- Button *b;
- int r = 0;
-
- assert(m);
-
- HASHMAP_FOREACH(b, m->buttons, i) {
- int q;
-
- q = button_recheck(b);
- if (q > 0)
- return 1;
- if (q < 0)
- r = q;
- }
-
- return r;
-}
-
int manager_run(Manager *m) {
int r;
if (manager_dispatch_delayed(m) > 0)
continue;
- if (manager_recheck_buttons(m) > 0)
- continue;
-
if (m->action_what != 0 && !m->action_job) {
usec_t x, y;
if (r < 0)
return r;
}
-
- return 0;
}
static int manager_parse_config_file(Manager *m) {
- static const char fn[] = "/etc/systemd/logind.conf";
- _cleanup_fclose_ FILE *f = NULL;
- int r;
-
assert(m);
- f = fopen(fn, "re");
- if (!f) {
- if (errno == ENOENT)
- return 0;
-
- log_warning("Failed to open configuration file %s: %m", fn);
- return -errno;
- }
-
- r = config_parse(NULL, fn, f, "Login\0", config_item_perf_lookup,
- (void*) logind_gperf_lookup, false, false, m);
- if (r < 0)
- log_warning("Failed to parse configuration file: %s", strerror(-r));
-
- return r;
+ return config_parse(NULL, "/etc/systemd/logind.conf", NULL,
+ "Login\0",
+ config_item_perf_lookup, logind_gperf_lookup,
+ false, false, true, m);
}
int main(int argc, char *argv[]) {
goto finish;
}
- log_debug("systemd-logind running as pid %lu", (unsigned long) getpid());
+ log_debug("systemd-logind running as pid "PID_FMT, getpid());
sd_notify(false,
"READY=1\n"
r = manager_run(m);
- log_debug("systemd-logind stopped as pid %lu", (unsigned long) getpid());
+ log_debug("systemd-logind stopped as pid "PID_FMT, getpid());
finish:
sd_notify(false,