尝试获取自定义类型的DBus属性时发生致命错误

问题描述:

我试图将UDisks2与Qt应用程序接口,并读取自定义属性使程序崩溃。尝试获取自定义类型的DBus属性时发生致命错误

对于SMART属性,一切都OK了(包括custom properties),但是当我尝试读取RAID设备的属性ActiveDevices我收到了Qt的致命错误和应用程序崩溃

下面是一个测试程序,它说明行为:

#include <QApplication> 

#include <QDBusMetaType> 
#include <QDBusConnection> 
#include <QDBusInterface> 

#include <QDebug> 


//create the structure as defined in 
// http://udisks.freedesktop.org/docs/latest/gdbus-org.freedesktop.UDisks2.MDRaid.html#gdbus-property-org-freedesktop-UDisks2-MDRaid.ActiveDevices 
struct MDRaidMember { 
    QDBusObjectPath block; 
    qint32 slot; 
    QStringList state; 
    qint64 numReadErrors; 
    QVariantMap expansion; 
}; 
Q_DECLARE_METATYPE(MDRaidMember) 


//marshalling operator 
QDBusArgument &operator<<(QDBusArgument &argument, const MDRaidMember& raidMember) 
{ 
    argument.beginStructure(); 
    argument << raidMember.block; 
    argument << raidMember.slot; 
    argument << raidMember.state; 
    argument << raidMember.numReadErrors; 
    argument << raidMember.expansion; 
    argument.endStructure(); 
    return argument; 
} 


//unmarshall operator 
const QDBusArgument &operator>>(const QDBusArgument &argument, MDRaidMember& raidMember) 
{ 
    argument.beginStructure(); 
    argument >> raidMember.block; 
    argument >> raidMember.slot; 
    argument >> raidMember.state; 
    argument >> raidMember.numReadErrors; 
    argument >> raidMember.expansion; 
    argument.endStructure(); 
    return argument; 
} 



int main(int argc, char *argv[]) { 
    QApplication app(argc, argv); 

    //register the type, everything looks fine 
    qDebug() << qRegisterMetaType<MDRaidMember>("MDRaidMember"); 
    qDebug() << qDBusRegisterMetaType<MDRaidMember>(); 


    QDBusInterface iface("org.freedesktop.UDisks2", 
         "/org/freedesktop/UDisks2/mdraid/9aec6784_86ec37d4_8c1c6add_4dc9fe81", 
         "org.freedesktop.UDisks2.MDRaid", 
         QDBusConnection::systemBus()); 

    //read some properties 
    qDebug() << iface.property("UUID"); 
    qDebug() << iface.property("ActiveDevices"); //crash the test program! 

    return app.exec(); 
} 

执行此代码生成以下输出

1057 
1057 
QVariant(QString, "9aec6784:86ec37d4:8c1c6add:4dc9fe81") 
Cannot construct placeholder type QDBusRawType 
zsh: abort (core dumped) ./app/test_members 

任何人遇到这种情况?我没有把它和我的代码联系起来,因为如果自定义类型没有被声明(只保留函数的内容),结果是一样的。

+0

我面对完全相同的问题进行UDisks2。 – Orient 2017-11-16 06:08:24

我没有找到正确的答案,但这里有一个解决方法:在接口org.freedesktop.DBus.Properties上调用Get方法并手动解组。最棘手的部分是断定结果的内容(这是包含QDBusVariant含有QDBusArgument一个的QVariant

更新main功能:

//... 

int main(int argc, char *argv[]) { 
    QApplication app(argc, argv); 

    //register the type, everything looks fine 
    qDebug() << qRegisterMetaType<MDRaidMember>("MDRaidMember"); 
    qDebug() << qDBusRegisterMetaType<MDRaidMember>(); 


    QDBusInterface iface("org.freedesktop.UDisks2", 
        "/org/freedesktop/UDisks2/mdraid/9aec6784_86ec37d4_8c1c6add_4dc9fe81", 
        "org.freedesktop.DBus.Properties", 
        QDBusConnection::systemBus()); 

    QDBusMessage reply = iface.call("Get", "org.freedesktop.UDisks2.MDRaid", "ActiveDevices"); 
    QVariant v = reply.arguments().first(); 
    QDBusArgument arg = v.value<QDBusVariant>().variant().value<QDBusArgument>(); 

    QList<MDRaidMember> members; 
    arg.beginArray(); 
    while(!arg.atEnd()) { 
    MDRaidMember m; 
    arg >> m; 
    members << m; 
    } 

    qDebug() << members; 

    return app.exec(); 
} 
+0

有没有无证的['qdbus_cast (QVariant)'](https://github.com/openwebos/qt/blob/master/src/dbus/qdbusargument.h#L166)专门用于这些目的的重载。 – Orient 2017-11-16 07:00:20