1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2011 Lennart Poettering
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
28 #include <sys/timerfd.h>
30 #include "sd-daemon.h"
32 #include "conf-parser.h"
35 #include "bus-error.h"
37 #include "udev-util.h"
39 Manager
*manager_new(void) {
47 m
->console_active_fd
= -1;
48 m
->reserve_vt_fd
= -1;
53 m
->inhibit_delay_max
= 5 * USEC_PER_SEC
;
54 m
->handle_power_key
= HANDLE_POWEROFF
;
55 m
->handle_suspend_key
= HANDLE_SUSPEND
;
56 m
->handle_hibernate_key
= HANDLE_HIBERNATE
;
57 m
->handle_lid_switch
= HANDLE_SUSPEND
;
58 m
->lid_switch_ignore_inhibited
= true;
60 m
->idle_action_usec
= 30 * USEC_PER_MINUTE
;
61 m
->idle_action
= HANDLE_IGNORE
;
62 m
->idle_action_not_before_usec
= now(CLOCK_MONOTONIC
);
64 m
->runtime_dir_size
= PAGE_ALIGN((size_t) (physical_memory() / 10)); /* 10% */
66 m
->devices
= hashmap_new(string_hash_func
, string_compare_func
);
67 m
->seats
= hashmap_new(string_hash_func
, string_compare_func
);
68 m
->sessions
= hashmap_new(string_hash_func
, string_compare_func
);
69 m
->users
= hashmap_new(trivial_hash_func
, trivial_compare_func
);
70 m
->inhibitors
= hashmap_new(string_hash_func
, string_compare_func
);
71 m
->buttons
= hashmap_new(string_hash_func
, string_compare_func
);
73 m
->user_units
= hashmap_new(string_hash_func
, string_compare_func
);
74 m
->session_units
= hashmap_new(string_hash_func
, string_compare_func
);
76 m
->busnames
= set_new(string_hash_func
, string_compare_func
);
78 if (!m
->devices
|| !m
->seats
|| !m
->sessions
|| !m
->users
|| !m
->inhibitors
|| !m
->buttons
|| !m
->busnames
||
79 !m
->user_units
|| !m
->session_units
)
82 m
->kill_exclude_users
= strv_new("root", NULL
);
83 if (!m
->kill_exclude_users
)
90 r
= sd_event_default(&m
->event
);
94 sd_event_set_watchdog(m
->event
, true);
103 void manager_free(Manager
*m
) {
113 while ((session
= hashmap_first(m
->sessions
)))
114 session_free(session
);
116 while ((u
= hashmap_first(m
->users
)))
119 while ((d
= hashmap_first(m
->devices
)))
122 while ((s
= hashmap_first(m
->seats
)))
125 while ((i
= hashmap_first(m
->inhibitors
)))
128 while ((b
= hashmap_first(m
->buttons
)))
131 hashmap_free(m
->devices
);
132 hashmap_free(m
->seats
);
133 hashmap_free(m
->sessions
);
134 hashmap_free(m
->users
);
135 hashmap_free(m
->inhibitors
);
136 hashmap_free(m
->buttons
);
138 hashmap_free(m
->user_units
);
139 hashmap_free(m
->session_units
);
141 set_free_free(m
->busnames
);
143 sd_event_source_unref(m
->idle_action_event_source
);
145 sd_event_source_unref(m
->console_active_event_source
);
146 sd_event_source_unref(m
->udev_seat_event_source
);
147 sd_event_source_unref(m
->udev_device_event_source
);
148 sd_event_source_unref(m
->udev_vcsa_event_source
);
149 sd_event_source_unref(m
->udev_button_event_source
);
150 sd_event_source_unref(m
->lid_switch_ignore_event_source
);
152 safe_close(m
->console_active_fd
);
154 if (m
->udev_seat_monitor
)
155 udev_monitor_unref(m
->udev_seat_monitor
);
156 if (m
->udev_device_monitor
)
157 udev_monitor_unref(m
->udev_device_monitor
);
158 if (m
->udev_vcsa_monitor
)
159 udev_monitor_unref(m
->udev_vcsa_monitor
);
160 if (m
->udev_button_monitor
)
161 udev_monitor_unref(m
->udev_button_monitor
);
166 bus_verify_polkit_async_registry_free(m
->polkit_registry
);
168 sd_bus_unref(m
->bus
);
169 sd_event_unref(m
->event
);
171 safe_close(m
->reserve_vt_fd
);
173 strv_free(m
->kill_only_users
);
174 strv_free(m
->kill_exclude_users
);
180 static int manager_enumerate_devices(Manager
*m
) {
181 struct udev_list_entry
*item
= NULL
, *first
= NULL
;
182 _cleanup_udev_enumerate_unref_
struct udev_enumerate
*e
= NULL
;
187 /* Loads devices from udev and creates seats for them as
190 e
= udev_enumerate_new(m
->udev
);
194 r
= udev_enumerate_add_match_tag(e
, "master-of-seat");
198 r
= udev_enumerate_add_match_is_initialized(e
);
202 r
= udev_enumerate_scan_devices(e
);
206 first
= udev_enumerate_get_list_entry(e
);
207 udev_list_entry_foreach(item
, first
) {
208 _cleanup_udev_device_unref_
struct udev_device
*d
= NULL
;
211 d
= udev_device_new_from_syspath(m
->udev
, udev_list_entry_get_name(item
));
215 k
= manager_process_seat_device(m
, d
);
223 static int manager_enumerate_buttons(Manager
*m
) {
224 _cleanup_udev_enumerate_unref_
struct udev_enumerate
*e
= NULL
;
225 struct udev_list_entry
*item
= NULL
, *first
= NULL
;
230 /* Loads buttons from udev */
232 if (m
->handle_power_key
== HANDLE_IGNORE
&&
233 m
->handle_suspend_key
== HANDLE_IGNORE
&&
234 m
->handle_hibernate_key
== HANDLE_IGNORE
&&
235 m
->handle_lid_switch
== HANDLE_IGNORE
)
238 e
= udev_enumerate_new(m
->udev
);
242 r
= udev_enumerate_add_match_subsystem(e
, "input");
246 r
= udev_enumerate_add_match_tag(e
, "power-switch");
250 r
= udev_enumerate_add_match_is_initialized(e
);
254 r
= udev_enumerate_scan_devices(e
);
258 first
= udev_enumerate_get_list_entry(e
);
259 udev_list_entry_foreach(item
, first
) {
260 _cleanup_udev_device_unref_
struct udev_device
*d
= NULL
;
263 d
= udev_device_new_from_syspath(m
->udev
, udev_list_entry_get_name(item
));
267 k
= manager_process_button_device(m
, d
);
275 static int manager_enumerate_seats(Manager
*m
) {
276 _cleanup_closedir_
DIR *d
= NULL
;
282 /* This loads data about seats stored on disk, but does not
283 * actually create any seats. Removes data of seats that no
286 d
= opendir("/run/systemd/seats");
291 log_error("Failed to open /run/systemd/seats: %m");
295 FOREACH_DIRENT(de
, d
, return -errno
) {
299 if (!dirent_is_file(de
))
302 s
= hashmap_get(m
->seats
, de
->d_name
);
304 unlinkat(dirfd(d
), de
->d_name
, 0);
316 static int manager_enumerate_linger_users(Manager
*m
) {
317 _cleanup_closedir_
DIR *d
= NULL
;
323 d
= opendir("/var/lib/systemd/linger");
328 log_error("Failed to open /var/lib/systemd/linger/: %m");
332 FOREACH_DIRENT(de
, d
, return -errno
) {
335 if (!dirent_is_file(de
))
338 k
= manager_add_user_by_name(m
, de
->d_name
, NULL
);
340 log_notice("Couldn't add lingering user %s: %s", de
->d_name
, strerror(-k
));
348 static int manager_enumerate_users(Manager
*m
) {
349 _cleanup_closedir_
DIR *d
= NULL
;
355 /* Add lingering users */
356 r
= manager_enumerate_linger_users(m
);
358 /* Read in user data stored on disk */
359 d
= opendir("/run/systemd/users");
364 log_error("Failed to open /run/systemd/users: %m");
368 FOREACH_DIRENT(de
, d
, return -errno
) {
371 if (!dirent_is_file(de
))
374 k
= manager_add_user_by_name(m
, de
->d_name
, &u
);
376 log_error("Failed to add user by file name %s: %s", de
->d_name
, strerror(-k
));
382 user_add_to_gc_queue(u
);
392 static int manager_enumerate_sessions(Manager
*m
) {
393 _cleanup_closedir_
DIR *d
= NULL
;
399 /* Read in session data stored on disk */
400 d
= opendir("/run/systemd/sessions");
405 log_error("Failed to open /run/systemd/sessions: %m");
409 FOREACH_DIRENT(de
, d
, return -errno
) {
413 if (!dirent_is_file(de
))
416 if (!session_id_valid(de
->d_name
)) {
417 log_warning("Invalid session file name '%s', ignoring.", de
->d_name
);
422 k
= manager_add_session(m
, de
->d_name
, &s
);
424 log_error("Failed to add session by file name %s: %s", de
->d_name
, strerror(-k
));
430 session_add_to_gc_queue(s
);
440 static int manager_enumerate_inhibitors(Manager
*m
) {
441 _cleanup_closedir_
DIR *d
= NULL
;
447 d
= opendir("/run/systemd/inhibit");
452 log_error("Failed to open /run/systemd/inhibit: %m");
456 FOREACH_DIRENT(de
, d
, return -errno
) {
460 if (!dirent_is_file(de
))
463 k
= manager_add_inhibitor(m
, de
->d_name
, &i
);
465 log_notice("Couldn't add inhibitor %s: %s", de
->d_name
, strerror(-k
));
470 k
= inhibitor_load(i
);
478 static int manager_dispatch_seat_udev(sd_event_source
*s
, int fd
, uint32_t revents
, void *userdata
) {
479 _cleanup_udev_device_unref_
struct udev_device
*d
= NULL
;
480 Manager
*m
= userdata
;
484 d
= udev_monitor_receive_device(m
->udev_seat_monitor
);
488 manager_process_seat_device(m
, d
);
492 static int manager_dispatch_device_udev(sd_event_source
*s
, int fd
, uint32_t revents
, void *userdata
) {
493 _cleanup_udev_device_unref_
struct udev_device
*d
= NULL
;
494 Manager
*m
= userdata
;
498 d
= udev_monitor_receive_device(m
->udev_device_monitor
);
502 manager_process_seat_device(m
, d
);
506 static int manager_dispatch_vcsa_udev(sd_event_source
*s
, int fd
, uint32_t revents
, void *userdata
) {
507 _cleanup_udev_device_unref_
struct udev_device
*d
= NULL
;
508 Manager
*m
= userdata
;
513 d
= udev_monitor_receive_device(m
->udev_vcsa_monitor
);
517 name
= udev_device_get_sysname(d
);
519 /* Whenever a VCSA device is removed try to reallocate our
520 * VTs, to make sure our auto VTs never go away. */
522 if (name
&& startswith(name
, "vcsa") && streq_ptr(udev_device_get_action(d
), "remove"))
523 seat_preallocate_vts(m
->seat0
);
528 static int manager_dispatch_button_udev(sd_event_source
*s
, int fd
, uint32_t revents
, void *userdata
) {
529 _cleanup_udev_device_unref_
struct udev_device
*d
= NULL
;
530 Manager
*m
= userdata
;
534 d
= udev_monitor_receive_device(m
->udev_button_monitor
);
538 manager_process_button_device(m
, d
);
542 static int manager_dispatch_console(sd_event_source
*s
, int fd
, uint32_t revents
, void *userdata
) {
543 Manager
*m
= userdata
;
547 assert(m
->console_active_fd
== fd
);
549 seat_read_active_vt(m
->seat0
);
553 static int manager_reserve_vt(Manager
*m
) {
554 _cleanup_free_
char *p
= NULL
;
558 if (m
->reserve_vt
<= 0)
561 if (asprintf(&p
, "/dev/tty%u", m
->reserve_vt
) < 0)
564 m
->reserve_vt_fd
= open(p
, O_RDWR
|O_NOCTTY
|O_CLOEXEC
|O_NONBLOCK
);
565 if (m
->reserve_vt_fd
< 0) {
567 /* Don't complain on VT-less systems */
569 log_warning("Failed to pin reserved VT: %m");
576 static int manager_connect_bus(Manager
*m
) {
577 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
583 r
= sd_bus_default_system(&m
->bus
);
585 log_error("Failed to connect to system bus: %s", strerror(-r
));
589 r
= sd_bus_add_object_vtable(m
->bus
, NULL
, "/org/freedesktop/login1", "org.freedesktop.login1.Manager", manager_vtable
, m
);
591 log_error("Failed to add manager object vtable: %s", strerror(-r
));
595 r
= sd_bus_add_fallback_vtable(m
->bus
, NULL
, "/org/freedesktop/login1/seat", "org.freedesktop.login1.Seat", seat_vtable
, seat_object_find
, m
);
597 log_error("Failed to add seat object vtable: %s", strerror(-r
));
601 r
= sd_bus_add_node_enumerator(m
->bus
, NULL
, "/org/freedesktop/login1/seat", seat_node_enumerator
, m
);
603 log_error("Failed to add seat enumerator: %s", strerror(-r
));
607 r
= sd_bus_add_fallback_vtable(m
->bus
, NULL
, "/org/freedesktop/login1/session", "org.freedesktop.login1.Session", session_vtable
, session_object_find
, m
);
609 log_error("Failed to add session object vtable: %s", strerror(-r
));
613 r
= sd_bus_add_node_enumerator(m
->bus
, NULL
, "/org/freedesktop/login1/session", session_node_enumerator
, m
);
615 log_error("Failed to add session enumerator: %s", strerror(-r
));
619 r
= sd_bus_add_fallback_vtable(m
->bus
, NULL
, "/org/freedesktop/login1/user", "org.freedesktop.login1.User", user_vtable
, user_object_find
, m
);
621 log_error("Failed to add user object vtable: %s", strerror(-r
));
625 r
= sd_bus_add_node_enumerator(m
->bus
, NULL
, "/org/freedesktop/login1/user", user_node_enumerator
, m
);
627 log_error("Failed to add user enumerator: %s", strerror(-r
));
631 r
= sd_bus_add_match(m
->bus
,
634 "sender='org.freedesktop.DBus',"
635 "interface='org.freedesktop.DBus',"
636 "member='NameOwnerChanged',"
637 "path='/org/freedesktop/DBus'",
638 match_name_owner_changed
, m
);
640 log_error("Failed to add match for NameOwnerChanged: %s", strerror(-r
));
644 r
= sd_bus_add_match(m
->bus
,
647 "sender='org.freedesktop.systemd1',"
648 "interface='org.freedesktop.systemd1.Manager',"
649 "member='JobRemoved',"
650 "path='/org/freedesktop/systemd1'",
651 match_job_removed
, m
);
653 log_error("Failed to add match for JobRemoved: %s", strerror(-r
));
657 r
= sd_bus_add_match(m
->bus
,
660 "sender='org.freedesktop.systemd1',"
661 "interface='org.freedesktop.systemd1.Manager',"
662 "member='UnitRemoved',"
663 "path='/org/freedesktop/systemd1'",
664 match_unit_removed
, m
);
666 log_error("Failed to add match for UnitRemoved: %s", strerror(-r
));
670 r
= sd_bus_add_match(m
->bus
,
673 "sender='org.freedesktop.systemd1',"
674 "interface='org.freedesktop.DBus.Properties',"
675 "member='PropertiesChanged'",
676 match_properties_changed
, m
);
678 log_error("Failed to add match for PropertiesChanged: %s", strerror(-r
));
682 r
= sd_bus_add_match(m
->bus
,
685 "sender='org.freedesktop.systemd1',"
686 "interface='org.freedesktop.systemd1.Manager',"
687 "member='Reloading',"
688 "path='/org/freedesktop/systemd1'",
691 log_error("Failed to add match for Reloading: %s", strerror(-r
));
695 r
= sd_bus_call_method(
697 "org.freedesktop.systemd1",
698 "/org/freedesktop/systemd1",
699 "org.freedesktop.systemd1.Manager",
704 log_error("Failed to enable subscription: %s", bus_error_message(&error
, r
));
708 r
= sd_bus_request_name(m
->bus
, "org.freedesktop.login1", 0);
710 log_error("Failed to register name: %s", strerror(-r
));
714 r
= sd_bus_attach_event(m
->bus
, m
->event
, 0);
716 log_error("Failed to attach bus to event loop: %s", strerror(-r
));
723 static int manager_vt_switch(sd_event_source
*src
, const struct signalfd_siginfo
*si
, void *data
) {
725 Session
*active
, *iter
;
728 * We got a VT-switch signal and we have to acknowledge it immediately.
729 * Preferably, we'd just use m->seat0->active->vtfd, but unfortunately,
730 * old user-space might run multiple sessions on a single VT, *sigh*.
731 * Therefore, we have to iterate all sessions and find one with a vtfd
732 * on the requested VT.
733 * As only VTs with active controllers have VT_PROCESS set, our current
734 * notion of the active VT might be wrong (for instance if the switch
735 * happens while we setup VT_PROCESS). Therefore, read the current VT
736 * first and then use s->active->vtnr as reference. Note that this is
737 * not racy, as no further VT-switch can happen as long as we're in
738 * synchronous VT_PROCESS mode.
742 seat_read_active_vt(m
->seat0
);
744 active
= m
->seat0
->active
;
745 if (!active
|| active
->vtnr
< 1) {
746 log_warning("Received VT_PROCESS signal without a registered session on that VT.");
750 if (active
->vtfd
>= 0) {
751 ioctl(active
->vtfd
, VT_RELDISP
, 1);
753 LIST_FOREACH(sessions_by_seat
, iter
, m
->seat0
->sessions
) {
754 if (iter
->vtnr
== active
->vtnr
&& iter
->vtfd
>= 0) {
755 ioctl(iter
->vtfd
, VT_RELDISP
, 1);
764 static int manager_connect_console(Manager
*m
) {
768 assert(m
->console_active_fd
< 0);
770 /* On certain architectures (S390 and Xen, and containers),
771 /dev/tty0 does not exist, so don't fail if we can't open
773 if (access("/dev/tty0", F_OK
) < 0)
776 m
->console_active_fd
= open("/sys/class/tty/tty0/active", O_RDONLY
|O_NOCTTY
|O_CLOEXEC
);
777 if (m
->console_active_fd
< 0) {
779 /* On some systems the device node /dev/tty0 may exist
780 * even though /sys/class/tty/tty0 does not. */
784 log_error("Failed to open /sys/class/tty/tty0/active: %m");
788 r
= sd_event_add_io(m
->event
, &m
->console_active_event_source
, m
->console_active_fd
, 0, manager_dispatch_console
, m
);
790 log_error("Failed to watch foreground console");
795 * SIGRTMIN is used as global VT-release signal, SIGRTMIN + 1 is used
796 * as VT-acquire signal. We ignore any acquire-events (yes, we still
797 * have to provide a valid signal-number for it!) and acknowledge all
798 * release events immediately.
801 if (SIGRTMIN
+ 1 > SIGRTMAX
) {
802 log_error("Not enough real-time signals available: %u-%u", SIGRTMIN
, SIGRTMAX
);
806 r
= ignore_signals(SIGRTMIN
+ 1, -1);
808 log_error("Cannot ignore SIGRTMIN + 1: %s", strerror(-r
));
812 r
= sigprocmask_many(SIG_BLOCK
, SIGRTMIN
, -1);
814 log_error("Cannot block SIGRTMIN: %s", strerror(-r
));
818 r
= sd_event_add_signal(m
->event
, NULL
, SIGRTMIN
, manager_vt_switch
, m
);
825 static int manager_connect_udev(Manager
*m
) {
829 assert(!m
->udev_seat_monitor
);
830 assert(!m
->udev_device_monitor
);
831 assert(!m
->udev_vcsa_monitor
);
832 assert(!m
->udev_button_monitor
);
834 m
->udev_seat_monitor
= udev_monitor_new_from_netlink(m
->udev
, "udev");
835 if (!m
->udev_seat_monitor
)
838 r
= udev_monitor_filter_add_match_tag(m
->udev_seat_monitor
, "master-of-seat");
842 r
= udev_monitor_enable_receiving(m
->udev_seat_monitor
);
846 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
);
850 m
->udev_device_monitor
= udev_monitor_new_from_netlink(m
->udev
, "udev");
851 if (!m
->udev_device_monitor
)
854 r
= udev_monitor_filter_add_match_subsystem_devtype(m
->udev_device_monitor
, "input", NULL
);
858 r
= udev_monitor_filter_add_match_subsystem_devtype(m
->udev_device_monitor
, "graphics", NULL
);
862 r
= udev_monitor_filter_add_match_subsystem_devtype(m
->udev_device_monitor
, "drm", NULL
);
866 r
= udev_monitor_enable_receiving(m
->udev_device_monitor
);
870 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
);
874 /* Don't watch keys if nobody cares */
875 if (m
->handle_power_key
!= HANDLE_IGNORE
||
876 m
->handle_suspend_key
!= HANDLE_IGNORE
||
877 m
->handle_hibernate_key
!= HANDLE_IGNORE
||
878 m
->handle_lid_switch
!= HANDLE_IGNORE
) {
880 m
->udev_button_monitor
= udev_monitor_new_from_netlink(m
->udev
, "udev");
881 if (!m
->udev_button_monitor
)
884 r
= udev_monitor_filter_add_match_tag(m
->udev_button_monitor
, "power-switch");
888 r
= udev_monitor_filter_add_match_subsystem_devtype(m
->udev_button_monitor
, "input", NULL
);
892 r
= udev_monitor_enable_receiving(m
->udev_button_monitor
);
896 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
);
901 /* Don't bother watching VCSA devices, if nobody cares */
902 if (m
->n_autovts
> 0 && m
->console_active_fd
>= 0) {
904 m
->udev_vcsa_monitor
= udev_monitor_new_from_netlink(m
->udev
, "udev");
905 if (!m
->udev_vcsa_monitor
)
908 r
= udev_monitor_filter_add_match_subsystem_devtype(m
->udev_vcsa_monitor
, "vc", NULL
);
912 r
= udev_monitor_enable_receiving(m
->udev_vcsa_monitor
);
916 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
);
924 void manager_gc(Manager
*m
, bool drop_not_started
) {
931 while ((seat
= m
->seat_gc_queue
)) {
932 LIST_REMOVE(gc_queue
, m
->seat_gc_queue
, seat
);
933 seat
->in_gc_queue
= false;
935 if (!seat_check_gc(seat
, drop_not_started
)) {
936 seat_stop(seat
, false);
941 while ((session
= m
->session_gc_queue
)) {
942 LIST_REMOVE(gc_queue
, m
->session_gc_queue
, session
);
943 session
->in_gc_queue
= false;
945 /* First, if we are not closing yet, initiate stopping */
946 if (!session_check_gc(session
, drop_not_started
) &&
947 session_get_state(session
) != SESSION_CLOSING
)
948 session_stop(session
, false);
950 /* Normally, this should make the session busy again,
951 * if it doesn't then let's get rid of it
953 if (!session_check_gc(session
, drop_not_started
)) {
954 session_finalize(session
);
955 session_free(session
);
959 while ((user
= m
->user_gc_queue
)) {
960 LIST_REMOVE(gc_queue
, m
->user_gc_queue
, user
);
961 user
->in_gc_queue
= false;
963 /* First step: queue stop jobs */
964 if (!user_check_gc(user
, drop_not_started
))
965 user_stop(user
, false);
967 /* Second step: finalize user */
968 if (!user_check_gc(user
, drop_not_started
)) {
975 static int manager_dispatch_idle_action(sd_event_source
*s
, uint64_t t
, void *userdata
) {
976 Manager
*m
= userdata
;
977 struct dual_timestamp since
;
983 if (m
->idle_action
== HANDLE_IGNORE
||
984 m
->idle_action_usec
<= 0)
987 n
= now(CLOCK_MONOTONIC
);
989 r
= manager_get_idle_hint(m
, &since
);
991 /* Not idle. Let's check if after a timeout it might be idle then. */
992 elapse
= n
+ m
->idle_action_usec
;
994 /* Idle! Let's see if it's time to do something, or if
995 * we shall sleep for longer. */
997 if (n
>= since
.monotonic
+ m
->idle_action_usec
&&
998 (m
->idle_action_not_before_usec
<= 0 || n
>= m
->idle_action_not_before_usec
+ m
->idle_action_usec
)) {
999 log_info("System idle. Taking action.");
1001 manager_handle_action(m
, 0, m
->idle_action
, false, false);
1002 m
->idle_action_not_before_usec
= n
;
1005 elapse
= MAX(since
.monotonic
, m
->idle_action_not_before_usec
) + m
->idle_action_usec
;
1008 if (!m
->idle_action_event_source
) {
1010 r
= sd_event_add_time(
1012 &m
->idle_action_event_source
,
1014 elapse
, USEC_PER_SEC
*30,
1015 manager_dispatch_idle_action
, m
);
1017 log_error("Failed to add idle event source: %s", strerror(-r
));
1021 r
= sd_event_source_set_priority(m
->idle_action_event_source
, SD_EVENT_PRIORITY_IDLE
+10);
1023 log_error("Failed to set idle event source priority: %s", strerror(-r
));
1027 r
= sd_event_source_set_time(m
->idle_action_event_source
, elapse
);
1029 log_error("Failed to set idle event timer: %s", strerror(-r
));
1033 r
= sd_event_source_set_enabled(m
->idle_action_event_source
, SD_EVENT_ONESHOT
);
1035 log_error("Failed to enable idle event timer: %s", strerror(-r
));
1043 int manager_startup(Manager
*m
) {
1049 Inhibitor
*inhibitor
;
1054 /* Connect to console */
1055 r
= manager_connect_console(m
);
1059 /* Connect to udev */
1060 r
= manager_connect_udev(m
);
1062 log_error("Failed to create udev watchers: %s", strerror(-r
));
1066 /* Connect to the bus */
1067 r
= manager_connect_bus(m
);
1071 /* Instantiate magic seat 0 */
1072 r
= manager_add_seat(m
, "seat0", &m
->seat0
);
1074 log_error("Failed to add seat0: %s", strerror(-r
));
1078 r
= manager_set_lid_switch_ignore(m
, 0 + IGNORE_LID_SWITCH_STARTUP_USEC
);
1080 log_warning("Failed to set up lid switch ignore event source: %s", strerror(-r
));
1082 /* Deserialize state */
1083 r
= manager_enumerate_devices(m
);
1085 log_warning("Device enumeration failed: %s", strerror(-r
));
1087 r
= manager_enumerate_seats(m
);
1089 log_warning("Seat enumeration failed: %s", strerror(-r
));
1091 r
= manager_enumerate_users(m
);
1093 log_warning("User enumeration failed: %s", strerror(-r
));
1095 r
= manager_enumerate_sessions(m
);
1097 log_warning("Session enumeration failed: %s", strerror(-r
));
1099 r
= manager_enumerate_inhibitors(m
);
1101 log_warning("Inhibitor enumeration failed: %s", strerror(-r
));
1103 r
= manager_enumerate_buttons(m
);
1105 log_warning("Button enumeration failed: %s", strerror(-r
));
1107 /* Remove stale objects before we start them */
1108 manager_gc(m
, false);
1110 /* Reserve the special reserved VT */
1111 manager_reserve_vt(m
);
1113 /* And start everything */
1114 HASHMAP_FOREACH(seat
, m
->seats
, i
)
1117 HASHMAP_FOREACH(user
, m
->users
, i
)
1120 HASHMAP_FOREACH(session
, m
->sessions
, i
)
1121 session_start(session
);
1123 HASHMAP_FOREACH(inhibitor
, m
->inhibitors
, i
)
1124 inhibitor_start(inhibitor
);
1126 HASHMAP_FOREACH(button
, m
->buttons
, i
)
1127 button_check_switches(button
);
1129 manager_dispatch_idle_action(NULL
, 0, m
);
1134 int manager_run(Manager
*m
) {
1140 usec_t us
= (uint64_t) -1;
1142 r
= sd_event_get_state(m
->event
);
1145 if (r
== SD_EVENT_FINISHED
)
1148 manager_gc(m
, true);
1150 if (manager_dispatch_delayed(m
) > 0)
1153 if (m
->action_what
!= 0 && !m
->action_job
) {
1156 x
= now(CLOCK_MONOTONIC
);
1157 y
= m
->action_timestamp
+ m
->inhibit_delay_max
;
1159 us
= x
>= y
? 0 : y
- x
;
1162 r
= sd_event_run(m
->event
, us
);
1168 static int manager_parse_config_file(Manager
*m
) {
1171 return config_parse(NULL
, "/etc/systemd/logind.conf", NULL
,
1173 config_item_perf_lookup
, logind_gperf_lookup
,
1174 false, false, true, m
);
1177 int main(int argc
, char *argv
[]) {
1181 log_set_target(LOG_TARGET_AUTO
);
1182 log_set_facility(LOG_AUTH
);
1183 log_parse_environment();
1189 log_error("This program takes no arguments.");
1194 /* Always create the directories people can create inotify
1195 * watches in. Note that some applications might check for the
1196 * existence of /run/systemd/seats/ to determine whether
1197 * logind is available, so please always make sure this check
1199 mkdir_label("/run/systemd/seats", 0755);
1200 mkdir_label("/run/systemd/users", 0755);
1201 mkdir_label("/run/systemd/sessions", 0755);
1209 manager_parse_config_file(m
);
1211 r
= manager_startup(m
);
1213 log_error("Failed to fully start up daemon: %s", strerror(-r
));
1217 log_debug("systemd-logind running as pid "PID_FMT
, getpid());
1221 "STATUS=Processing requests...");
1225 log_debug("systemd-logind stopped as pid "PID_FMT
, getpid());
1229 "STATUS=Shutting down...");
1234 return r
< 0 ? EXIT_FAILURE
: EXIT_SUCCESS
;