QtでDBusサービスが利用可能になるのを待っています
質問
QDbusAbstractInterfaceに(qdbusxml2cppを介して)構築されたQt DBusプロキシを使用して、起動時に利用できないようにインターフェイスするサービス/オブジェクトを処理する最良の方法は何ですか?注:単純にそれを知ることに興味はありません(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の例では、少なくともサーバーがなくなって「Disconnected」と表示されるかどうかがわかります。 isValid()が使用中にfalseになりますが、isValid()をポーリングしている場合。
追加:
QtDbusAbtractInterfaceはサーバーの所有権の変更(NameOwnerChanged)を登録し、変更が発生するとisValid()を更新することに注意してください。したがって、そのserverOwnerChangedシグナルに直接接続して所有権の変更を確認し、それを再試行のインジケーターとして使用できると思います-ただし、isValidは、シグナルを受け取る前または後に更新される可能性があるため、信頼できません。
代わりに(ugい)タイマーを設定し、isValid()をポーリングできます。
解決
わかりました、誰も答えなかったので、その間に答えを見つけました:
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メーリングリストのnoは質問に答えます)。実際の競合状態が ある場合、DBus APIを制御していれば、Ready()/ whateverシグナルを待つことができます。相手を制御しない場合は、非常に短い遅延を追加するか、AddMatch()を見て、新しい所有者が名前に一致するものを追加したことを確認することもできます。
他のヒント
Qt 5.3では、 serviceOwnerChanged
は非推奨です。 QDBusServiceWatcher
を使用して、すべてではなく特定のサービス。