检测 D-Bus 上的禁止关闭

Detect inhibited shutdown on D-Bus

我使用 x86_64 Debian 9 Stretch。我 运行 systemd-inhibit cat 然后在另一个控制台 systemctl poweroff。关机正确地被禁止。根据 this doc 信号 PrepareForShutdown(false) 应该发出,但我看不到。我用 dbus-monitor --system 和 python 程序观看 dbus:

#!/usr/bin/env python

import dbus
import gobject
from dbus.mainloop.glib import DBusGMainLoop

def handle(*args):
    print "PrepareForShutdown %s" % (args)

DBusGMainLoop(set_as_default=True)     # integrate into gobject main loop
bus = dbus.SystemBus()                 # connect to system wide dbus
bus.add_signal_receiver(               # define the signal to listen to
    handle,                            # callback function
    'PrepareForShutdown',              # signal name
    'org.freedesktop.login1.Manager',  # interface
    'org.freedesktop.login1'           # bus name
)

loop = gobject.MainLoop()
loop.run()

程序不打印任何内容。 dbus-monitor 输出一些晦涩的消息(看起来像是在调用 ListInhibitors)。

是信号没有发出,还是我就是抓不到?我的目标是通过侦听 D-Bus 来检测禁止关机,我该怎么做?

编辑:当使用非延迟抑制时结果是,关闭请求被丢弃,信号不触发。但是,如果我通过 systemd-inhibit --mode=delay --what=shutdown cat 使用延迟锁定,则会触发 PrepareForShutdown 信号。

Is signal not being emited or I just can't catch it?

不确定。我的猜测是 systemd 只向已经延迟锁定的进程发出信号(单播信号发射),因为如果你监听 PrepareForShutdown [=] documentation page 有一些关于竞争条件的非常可怕的警告43=]没有先获取延迟锁。

检查这一点的方法是阅读 systemd source code

My goal is to detect inhibited shutdown by listening D-Bus, how do I do it?

如果我在一个终端中 运行 sudo dbus-monitor --system,然后在另一个终端中 运行 systemd-inhibit cat,我会看到以下信号发射:

signal time=1543917703.712998 sender=:1.9 -> destination=(null destination) serial=1150 path=/org/freedesktop/login1; interface=org.freedesktop.DBus.Properties; member=PropertiesChanged
   string "org.freedesktop.login1.Manager"
   array [
      dict entry(
         string "BlockInhibited"
         variant             string "shutdown:sleep:idle:handle-power-key:handle-suspend-key:handle-hibernate-key:handle-lid-switch"
      )
   ]
   array [
   ]

因此,您可以观察服务 org.freedesktop.login1 公开的 /org/freedesktop/login1 对象的 属性 变化,并查看其 BlockInhibitedDelayInhibited 属性何时发生变化.当这些属性中的任何一个包含 shutdown 时,将禁止关机。它们记录在 the same documentation page:

The BlockInhibited and DelayInhibited properties encode what types of locks are currently taken. These fields are a colon separated list of shutdown, sleep, idle, handle-power-key, handle-suspend-key, handle-hibernate-key, handle-lid-switch. The list is basically the union of the What fields of all currently active locks of the specific mode.