Daniel Brötzmann pushed to branch master at gajim / gajim
Commits: 95e2ca1a by wurstsalat at 2022-06-14T20:41:57+02:00 feat: Logind: Listen to system shutdown and quit Gajim gracefully
Fixes #10040
- - - - -
2 changed files:
- gajim/common/application.py - gajim/common/dbus/logind.py
Changes:
===================================== gajim/common/application.py ===================================== @@ -36,6 +36,7 @@ from gajim.common import ged from gajim.common import configpaths from gajim.common import logging_helpers +from gajim.common.dbus import logind from gajim.common.events import AccountDisonnected from gajim.common.events import AllowGajimUpdateCheck from gajim.common.events import GajimUpdateAvailable @@ -87,6 +88,8 @@ def _init_core(self) -> None:
if sys.platform in ('win32', 'darwin'): GLib.timeout_add_seconds(20, self._check_for_updates) + else: + logind.enable()
for account in app.settings.get_active_accounts(): app.connections[account] = Client(account) @@ -174,6 +177,7 @@ def _shutdown_core(self) -> None: app.storage.cache.shutdown() app.storage.archive.shutdown() self.end_profiling() + logind.shutdown()
def _quit_app(self) -> None: self._shutdown_core()
===================================== gajim/common/dbus/logind.py ===================================== @@ -15,8 +15,8 @@ # along with Gajim. If not, see http://www.gnu.org/licenses/.
''' -Watch for system sleep using systemd-logind. -Documentation: http://www.freedesktop.org/wiki/Software/systemd/inhibit +Watch for system shutdown using systemd-logind. +Documentation: https://www.freedesktop.org/wiki/Software/systemd/inhibit ''' from __future__ import annotations
@@ -52,56 +52,36 @@ def __init__(self) -> None: Gio.BusType.SYSTEM, 'org.freedesktop.login1', Gio.BusNameWatcherFlags.NONE, - self._on_appear_logind, - self._on_vanish_logind) - - def _on_prepare_for_sleep(self, - connection: Gio.DBusConnection, - _sender_name: str, - _object_path: str, - interface_name: str, - signal_name: str, - parameters: tuple[str, str, str], - *_user_data: Any - ) -> None: - '''Signal handler for PrepareForSleep event''' + self._on_logind_appeared, + self._on_logind_vanished) + + def _on_prepare_for_shutdown(self, + _connection: Gio.DBusConnection, + _sender_name: str, + _object_path: str, + interface_name: str, + signal_name: str, + parameters: tuple[str, str, str], + *_user_data: Any + ) -> None: + '''Signal handler for PrepareForShutdown event''' log.debug('Received signal %s.%s%s', interface_name, signal_name, parameters)
- before = parameters[0] # Signal is either before or after sleep occurs - if before: - warn = self._inhibit_fd is None - log.log( - logging.WARNING if warn else logging.INFO, - 'Preparing for sleep by disconnecting from network%s', - ', without holding a sleep inhibitor' if warn else '') - - for name, conn in app.connections.items(): - if app.account_is_connected(name): - st = conn.status_message - conn.change_status('offline', - _('Machine is going to sleep')) - # TODO: Make this nicer - conn._status_message = st # pylint: disable=protected-access - conn.time_to_reconnect = 5 - - self._disinhibit_sleep() + if self._inhibit_fd is None: + log.warning('Preparing for shutdown by quitting Gajim, ' + 'without holding a shutdown inhibitor') else: - try: - self._inhibit_sleep(connection) - except GLib.Error as error: - log.warning('Inhibit failed: %s', error) + log.info('Preparing for shutdown by quitting Gajim')
- for conn in app.connections.values(): - if conn.state.is_disconnected and conn.time_to_reconnect: - conn.reconnect() + app.window.quit()
- def _inhibit_sleep(self, connection: Gio.DBusConnection) -> None: - '''Obtain a sleep delay inhibitor from logind''' + def _obtain_delay_inhibitor(self, connection: Gio.DBusConnection) -> None: + '''Obtain a shutdown delay inhibitor from logind''' if self._inhibit_fd is not None: # Something is wrong, we have an inhibitor fd, and we are asking for # yet another one. - log.warning('Trying to obtain a sleep inhibitor ' + log.warning('Trying to obtain a shutdown inhibitor ' 'while already holding one.')
try: @@ -111,10 +91,10 @@ def _inhibit_sleep(self, connection: Gio.DBusConnection) -> None: 'org.freedesktop.login1.Manager', 'Inhibit', GLib.Variant('(ssss)', ( - 'sleep', + 'shutdown', 'org.gajim.Gajim', - _('Disconnect from the network'), - 'delay' # Inhibitor will delay but not block sleep + _('Shutting down Gajim'), + 'delay' # Inhibitor will delay but not block shutdown )), GLib.VariantType.new('(h)'), Gio.DBusCallFlags.NONE, @@ -123,59 +103,58 @@ def _inhibit_sleep(self, connection: Gio.DBusConnection) -> None: None) if result is None: log.warning( - 'Cannot obtain a sleep delay inhibitor from logind') + 'Could not obtain a shutdown delay inhibitor from logind') return ret, ret_fdlist = result except GLib.Error as error: log.warning( - 'Cannot obtain a sleep delay inhibitor from logind: %s', error) + 'Could not obtain a shutdown delay inhibitor from ' + 'logind: %s', error) return
- log.info('Inhibit sleep') self._inhibit_fd = ret_fdlist.get(ret.unpack()[0]) + log.info('Obtained shutdown delay inhibitor')
- def _disinhibit_sleep(self) -> None: - '''Relinquish our sleep delay inhibitor''' + def release_delay_inhibitor(self) -> None: + '''Release our shutdown delay inhibitor''' if self._inhibit_fd is not None: os.close(self._inhibit_fd) self._inhibit_fd = None - log.info('Disinhibit sleep') - - def _on_appear_logind(self, - connection: Gio.DBusConnection, - name: str, - name_owner: str, - *_user_data: Any - ) -> None: + log.info('Released shutdown delay inhibitor') + + def _on_logind_appeared(self, + connection: Gio.DBusConnection, + name: str, + name_owner: str, + *_user_data: Any + ) -> None: '''Use signal and locks provided by org.freedesktop.login1''' log.info('Name %s appeared, owned by %s', name, name_owner)
connection.signal_subscribe( 'org.freedesktop.login1', 'org.freedesktop.login1.Manager', - 'PrepareForSleep', + 'PrepareForShutdown', '/org/freedesktop/login1', None, Gio.DBusSignalFlags.NONE, - self._on_prepare_for_sleep, + self._on_prepare_for_shutdown, None) - self._inhibit_sleep(connection) + self._obtain_delay_inhibitor(connection)
- def _on_vanish_logind(self, - _connection: Gio.DBusConnection, - name: str, - *_user_data: Any - ) -> None: + def _on_logind_vanished(self, + _connection: Gio.DBusConnection, + name: str, + *_user_data: Any + ) -> None: '''Release remaining resources related to org.freedesktop.login1''' log.info('Name %s vanished', name) - self._disinhibit_sleep() + self.release_delay_inhibitor()
def enable() -> None: - # Module should be rewritten - # Its not useful to know when the computer goes to sleep. - # Because of stream management we don’t need to do anything in that case. - # It would be useful to know when the computer powers off, in this case - # Gajim is shutdown and we should correctly disconnect. - return - # LogindListener.get() + LogindListener.get() + + +def shutdown() -> None: + LogindListener.get().release_delay_inhibitor()
View it on GitLab: https://dev.gajim.org/gajim/gajim/-/commit/95e2ca1aa380c9e703db34bed6ddb3869...