X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Flogin%2Flogind.c;h=ec5529db1a3868430d989c440bcab0cd0e68c560;hb=952f4b59592088f15615eb404c828aaac31bfe82;hp=e334bebdf84230ad8cf1db82918bc9650e326397;hpb=cc3773810855956bad92337cee8fa193584ab62e;p=elogind.git diff --git a/src/login/logind.c b/src/login/logind.c index e334bebdf..ec5529db1 100644 --- a/src/login/logind.c +++ b/src/login/logind.c @@ -34,6 +34,7 @@ #include "bus-util.h" #include "bus-error.h" #include "logind.h" +#include "udev-util.h" Manager *manager_new(void) { Manager *m; @@ -48,6 +49,7 @@ Manager *manager_new(void) { 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; @@ -59,6 +61,8 @@ Manager *manager_new(void) { 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); @@ -72,31 +76,28 @@ Manager *manager_new(void) { 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_new(&m->event); - if (r < 0) { - manager_free(m); - return NULL; - } + r = sd_event_default(&m->event); + 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) { @@ -146,9 +147,9 @@ 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); @@ -167,8 +168,7 @@ void manager_free(Manager *m) { 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); @@ -177,9 +177,9 @@ void manager_free(Manager *m) { free(m); } -int manager_enumerate_devices(Manager *m) { +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); @@ -188,47 +188,41 @@ int manager_enumerate_devices(Manager *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; } -int manager_enumerate_buttons(Manager *m) { +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); @@ -242,49 +236,43 @@ int manager_enumerate_buttons(Manager *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; } -int manager_enumerate_seats(Manager *m) { +static int manager_enumerate_seats(Manager *m) { _cleanup_closedir_ DIR *d = NULL; struct dirent *de; int r = 0; @@ -357,7 +345,7 @@ static int manager_enumerate_linger_users(Manager *m) { return r; } -int manager_enumerate_users(Manager *m) { +static int manager_enumerate_users(Manager *m) { _cleanup_closedir_ DIR *d = NULL; struct dirent *de; int r, k; @@ -401,7 +389,7 @@ int manager_enumerate_users(Manager *m) { return r; } -int manager_enumerate_sessions(Manager *m) { +static int manager_enumerate_sessions(Manager *m) { _cleanup_closedir_ DIR *d = NULL; struct dirent *de; int r = 0; @@ -449,7 +437,7 @@ int manager_enumerate_sessions(Manager *m) { return r; } -int manager_enumerate_inhibitors(Manager *m) { +static int manager_enumerate_inhibitors(Manager *m) { _cleanup_closedir_ DIR *d = NULL; struct dirent *de; int r = 0; @@ -488,9 +476,8 @@ int manager_enumerate_inhibitors(Manager *m) { } 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); @@ -498,16 +485,13 @@ static int manager_dispatch_seat_udev(sd_event_source *s, int fd, uint32_t reven 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); @@ -515,16 +499,13 @@ static int manager_dispatch_device_udev(sd_event_source *s, int fd, uint32_t rev 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); @@ -539,17 +520,14 @@ static int manager_dispatch_vcsa_udev(sd_event_source *s, int fd, uint32_t reven * 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); @@ -557,10 +535,8 @@ static int manager_dispatch_button_udev(sd_event_source *s, int fd, uint32_t rev 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) { @@ -571,7 +547,6 @@ static int manager_dispatch_console(sd_event_source *s, int fd, uint32_t revents assert(m->console_active_fd == fd); seat_read_active_vt(m->seat0); - return 0; } @@ -605,55 +580,56 @@ static int manager_connect_bus(Manager *m) { assert(m); assert(!m->bus); - r = sd_bus_open_system(&m->bus); + r = sd_bus_default_system(&m->bus); if (r < 0) { log_error("Failed to connect to system bus: %s", strerror(-r)); 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'," @@ -666,6 +642,7 @@ static int manager_connect_bus(Manager *m) { } r = sd_bus_add_match(m->bus, + NULL, "type='signal'," "sender='org.freedesktop.systemd1'," "interface='org.freedesktop.systemd1.Manager'," @@ -678,6 +655,7 @@ static int manager_connect_bus(Manager *m) { } r = sd_bus_add_match(m->bus, + NULL, "type='signal'," "sender='org.freedesktop.systemd1'," "interface='org.freedesktop.systemd1.Manager'," @@ -690,6 +668,7 @@ static int manager_connect_bus(Manager *m) { } r = sd_bus_add_match(m->bus, + NULL, "type='signal'," "sender='org.freedesktop.systemd1'," "interface='org.freedesktop.DBus.Properties'," @@ -701,6 +680,7 @@ static int manager_connect_bus(Manager *m) { } r = sd_bus_add_match(m->bus, + NULL, "type='signal'," "sender='org.freedesktop.systemd1'," "interface='org.freedesktop.systemd1.Manager'," @@ -725,17 +705,12 @@ static int manager_connect_bus(Manager *m) { return r; } - r = sd_bus_request_name(m->bus, "org.freedesktop.login1", SD_BUS_NAME_DO_NOT_QUEUE); + r = sd_bus_request_name(m->bus, "org.freedesktop.login1", 0); if (r < 0) { log_error("Failed to register name: %s", strerror(-r)); return r; } - if (r != SD_BUS_NAME_PRIMARY_OWNER) { - log_error("Failed to acquire name."); - return -EEXIST; - } - r = sd_bus_attach_event(m->bus, m->event, 0); if (r < 0) { log_error("Failed to attach bus to event loop: %s", strerror(-r)); @@ -769,7 +744,7 @@ static int manager_connect_console(Manager *m) { 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; @@ -799,7 +774,7 @@ static int manager_connect_udev(Manager *m) { 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; @@ -823,7 +798,7 @@ static int manager_connect_udev(Manager *m) { 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; @@ -849,7 +824,7 @@ static int manager_connect_udev(Manager *m) { 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; } @@ -869,7 +844,7 @@ static int manager_connect_udev(Manager *m) { 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; } @@ -889,7 +864,7 @@ void manager_gc(Manager *m, bool drop_not_started) { seat->in_gc_queue = false; if (!seat_check_gc(seat, drop_not_started)) { - seat_stop(seat); + seat_stop(seat, false); seat_free(seat); } } @@ -898,8 +873,15 @@ void manager_gc(Manager *m, bool drop_not_started) { 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); } @@ -909,8 +891,12 @@ void manager_gc(Manager *m, bool drop_not_started) { 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); } @@ -952,13 +938,18 @@ static int manager_dispatch_idle_action(sd_event_source *s, uint64_t t, void *us 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; } - r = sd_event_source_set_priority(m->idle_action_event_source, SD_PRIORITY_IDLE+10); + r = sd_event_source_set_priority(m->idle_action_event_source, SD_EVENT_PRIORITY_IDLE+10); if (r < 0) { log_error("Failed to set idle event source priority: %s", strerror(-r)); return r; @@ -985,6 +976,7 @@ int manager_startup(Manager *m) { Seat *seat; Session *session; User *user; + Button *button; Inhibitor *inhibitor; Iterator i; @@ -1014,6 +1006,10 @@ int manager_startup(Manager *m) { 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) @@ -1058,31 +1054,14 @@ int manager_startup(Manager *m) { 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; @@ -1102,9 +1081,6 @@ int manager_run(Manager *m) { 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; @@ -1118,32 +1094,15 @@ int manager_run(Manager *m) { 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[]) { @@ -1186,7 +1145,7 @@ 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" @@ -1194,7 +1153,7 @@ int main(int argc, char *argv[]) { 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,