【问题标题】:Waiting for a DBus service to be available in Qt等待 DBus 服务在 Qt 中可用
【发布时间】:2010-11-28 06:24:37
【问题描述】:

使用基于 QDbusAbstractInterface 构建的 Qt DBus 代理(通过 qdbusxml2cpp),处理您想要连接的服务/对象以使其在启动时不可用的最佳方式是什么?注意:我对简单地了解它不感兴趣(您可以使用 BlahService.isValid() 来找出它);我希望能够知道它是否有效,并且知道它何时有效,以便我可以更改状态(并用信号广播该状态更改),并在该状态更改上做其他事情。相反,我想知道由于类似原因它何时不再有效。

不跟踪服务状态:

#define CONNECT_DBUS_SIG(x,y) connect(blah,SIGNAL(x),this,SLOT(y))

// FIX - should watch for service, and also handle it going away and
// coming back
blah = new BlahService("com.xyzzy.BlahService", "/com/xyzzy/BlahService",
                           QDBusConnection::sessionBus(), this);
if (!blah)
    return 0;
if (blah.isValid())
{
    CONNECT_DBUS_SIG(foo(),Event_foo());
}
else
{
    // Since we aren't watching for registration, what can we do but exit?
}

可能我们需要观察 DBus 连接对象上的 NameOwnerChanged - 除非 QT 的 dbus 代码为我们执行此操作 - 然后当我们获得该信号更改状态时,如果需要连接或断开来自对象的信号。

我发现的所有示例要么忽略该问题,要么在服务器对象不存在时直接退出,并且不处理它消失。 Car/Controller Qt 示例至少会注意到服务器是否离开并在使用期间 isValid() 变为 false 时打印“Disconnected”,但它正在轮询 isValid()。

添加:

请注意,QtDbusAbtractInterface 注册服务器所有权的更改 (NameOwnerChanged),并在更改发生时更新 isValid()。因此,我怀疑您可以直接连接到该 serverOwnerChanged 信号以了解所有权更改并将其用作再试一次的指标 - 尽管您将无法信任 isValid 因为它可能会在您收到信号之前或之后更新。

或者(丑陋的)你可以设置一个计时器并轮询 isValid()。

【问题讨论】:

    标签: c++ linux qt qt4 dbus


    【解决方案1】:

    好的,由于没有人回答,我在此期间找到了答案:

    你想看 NameOwnerChanged:

    // subscribe to notifications about when a service is registered/unregistered
       connect(QDBusConnection::sessionBus().interface(),
               SIGNAL(serviceOwnerChanged(QString,QString,QString)),
               this,SLOT(serviceOwnerChanged(QString,QString,QString)));
    

    void 
    VcsApplicationController::serviceOwnerChanged(const QString &name,
                                                  const QString &oldOwner,
                                                  const QString &newOwner)
    {
        Q_UNUSED(oldOwner);
        if (name == "com.foo.bar.FooService")
        {
            qLog(Whatever) << "serviceOwnerChanged" << name << oldOwner << newOwner;
            if (!newOwner.isEmpty())
            {
                // New owner in town
                emit Initialized();
                // or if you control the interface and both sides, you can wait for
                // a "Ready()" signal before declaring FooService ready for business.
            }
            else
            {
                // indicate we've lost connection, etc
                emit Uninitialized();
            }
        }
    }
    

    请注意,可能在 serviceOwnerChanged 中对 FooService 执行方法时会出现竞争条件 - 我还不确定它们是否是绑定的副作用(我的测试中的 dbus-c++案例),或 dbus 设计中固有的(可能 - dbus 邮件列表上的任何人都不会回答这个问题)。如果存在真正的竞争条件,如果您控制 DBus API,您可以等待 Ready()/whatever 信号。如果您不控制另一端,您可以添加一个非常短的延迟,或者您也可以观看 AddMatch() 以确保新所有者也添加了名称上的匹配项。

    【讨论】:

    • 我用这条线只获取我想要的服务的信号:QDBusConnection::systemBus().connect("org.freedesktop.DBus", "/org/freedesktop/DBus", "org.freedesktop.DBus", "NameOwnerChanged", QStringList() &lt;&lt; "org.freedesktop.Avahi", "sss", this, SLOT(AvahiNameOwnerChanged(QString,QString,QString))); 至于竞争条件,我删除了我的旧接口,一旦我得到这个信号,我就会得到一个新的接口。跨度>
    【解决方案2】:

    在 Qt 5.3 中,serviceOwnerChanged 已弃用。使用QDBusServiceWatcher,它允许监视特定服务而不是全部。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-06-05
      • 1970-01-01
      • 2018-06-03
      • 1970-01-01
      • 2016-04-29
      • 2017-05-26
      • 2016-06-15
      相关资源
      最近更新 更多