g_signal_connect в обработчике прокси приводит к обратному вызову GVariant * data uninitialized

Я в значительной степени следую примеру на https://www.freedesktop.org/software/gstreamer-sdk/data/docs/latest/gio/GDBusProxy.html, чтобы настроить обратные вызовы сигнала Connman на dbus, однако в моей функции обратного вызова:

g_signal_connect(
        this->manager_proxy,
        "property-changed",
        G_CALLBACK(on_manager_properties_changed),
        this); //Pass in pointer to self so static function can operate on object.
g_signal_connect(
        this->manager_proxy,
        "technology-added",
        G_CALLBACK(on_manager_tech_added),
        this); //Pass in pointer to self so static function can operate on object.
g_signal_connect(
        this->manager_proxy,
        "technology-removed",
        G_CALLBACK(on_manager_tech_removed),
        this); //Pass in pointer to self so static function can operate on object

void
CM_InterfaceController::on_manager_properties_changed (
                       GDBusProxy          *proxy,
                       GVariant            *changed_properties,
                       const gchar* const  *invalidated_properties,
                       gpointer             user_data)
{
    if(!user_data){CM_ERR("NO THIS * on_manager_properties_changed");return;}
    CM_InterfaceController * ths = static_cast<CM_InterfaceController *>(user_data);
    std::cout<<"on_manager_properties_changed"<<std::endl;
    if(changed_properties){
        std::cout<<"children: "<<g_variant_n_children(changed_properties)<<std::endl;
    }    
}

Количество дочерних элементов, которое, как мне сказали, содержит объект GVariant *, совершенно неверно. Например, мой отзыв:

Calling Extraction
Service List Size: 1
Identified Ethernet Link: 
Path: /net/connman/service/ethernet_0800277d326e_cable
        Type: ethernet
        Sate: ready
        Favorite: 0
        Auto Connect: 0
        Name: Wired
        Net Mode: manual
        Iface: eth0
        Mac: 08:00:27:7D:32:6E
        IP Address: 10.0.2.15
        Net Mask: 255.255.255.0
on_manager_properties_changed
children: 139764141513856
on_manager_properties_changed
children: 145

дочерние элементы on_manager_properties_changed: 139764141513856 дочерние элементы on_manager_properties_changed: 145

Оба эти значения находятся далеко за пределами примерного, одно значительно больше, чем другое. Более того, если я попытаюсь разобрать значения из объекта GVariant, я закончу с ошибкой seg, даже просто попытавшись вызвать g_variant_get_type_string. С какой стати мой обратный вызов возвращает указатель на мусорные данные? Похоже, что если у него ничего нет, он должен по крайней мере возвращать нулевой указатель.

Изменить: https://drive.google.com/file/d/1E0Kg9JKW54gghUHbVyBJ0ysBIdqBlpVA/view?usp=sharing

И часть вывода dbus-monitor --system:

signal time=1549641357.679460 sender=:1.3 -> destination=(null destination) serial=488 path=/net/connman/service/ethernet_0800277d326e_cable; interface=net.connman.Service; member=PropertyChanged
   string "State"
   variant       string "ready"
signal time=1549641357.680844 sender=:1.3 -> destination=(null destination) serial=489 path=/net/connman/service/ethernet_0800277d326e_cable; interface=net.connman.Service; member=PropertyChanged
   string "Nameservers"
   variant       array [
         string "10.0.2.3"
      ]
signal time=1549641357.681186 sender=:1.3 -> destination=(null destination) serial=490 path=/net/connman/service/ethernet_0800277d326e_cable; interface=net.connman.Service; member=PropertyChanged
   string "Domains"
   variant       array [
      ]
signal time=1549641357.681601 sender=:1.3 -> destination=(null destination) serial=491 path=/net/connman/service/ethernet_0800277d326e_cable; interface=net.connman.Service; member=PropertyChanged
   string "Proxy"
   variant       array [
         dict entry(
            string "Method"
            variant                string "direct"
         )
      ]
signal time=1549641357.681780 sender=:1.3 -> destination=(null destination) serial=492 path=/net/connman/technology/ethernet; interface=net.connman.Technology; member=PropertyChanged
   string "Connected"
   variant       boolean true
signal time=1549641357.682210 sender=:1.3 -> destination=(null destination) serial=493 path=/; interface=net.connman.Manager; member=PropertyChanged
   string "State"
   variant       string "ready"
signal time=1549641357.696004 sender=:1.3 -> destination=(null destination) serial=494 path=/net/connman/service/ethernet_0800277d326e_cable; interface=net.connman.Service; member=PropertyChanged
   string "IPv4"
   variant       array [
         dict entry(
            string "Method"
            variant                string "dhcp"
         )
      ]
signal time=1549641357.696227 sender=:1.3 -> destination=(null destination) serial=495 path=/net/connman/service/ethernet_0800277d326e_cable; interface=net.connman.Service; member=PropertyChanged
   string "IPv4"
   variant       array [
         dict entry(
            string "Method"
            variant                string "dhcp"
         )
         dict entry(
            string "Address"
            variant                string "10.0.2.15"
         )
         dict entry(
            string "Netmask"
            variant                string "255.255.255.0"
         )
      ]
signal time=1549641357.696454 sender=:1.3 -> destination=(null destination) serial=496 path=/net/connman/service/ethernet_0800277d326e_cable; interface=net.connman.Service; member=PropertyChanged
   string "IPv4"
   variant       array [
         dict entry(
            string "Method"
            variant                string "dhcp"
         )
         dict entry(
            string "Address"
            variant                string "10.0.2.15"
         )
         dict entry(
            string "Netmask"
            variant                string "255.255.255.0"
         )
         dict entry(
            string "Gateway"
            variant                string "10.0.2.2"
         )
      ]

Захват объекта в памяти


person Tyler Cox    schedule 08.02.2019    source источник
comment
Итак, моя текущая теория заключается в том, что некоторые элементы моего XML-файла используются для генерации исходного кода gdbus из gdbus-codegen. Я только что проанализировал свою службу net.connman, и есть некоторые тонкие различия между тем, что она мне дала, и XML-файлом, который я сейчас использую. Похоже, что оба сигнала PropertyChanged одинаковы, так что это не делает меня очень близким к решению этой проблемы, но, возможно, это каким-то образом вызывает проблемы в фоновом режиме.   -  person Tyler Cox    schedule 08.02.2019
comment
Пробовал повторно выполнять интроспекцию на net.connman, а затем повторно запускать gdbus-codegen, но это не помогло.   -  person Tyler Cox    schedule 08.02.2019
comment
Я думаю, что это может быть как-то связано с инициализатором сигнала в сгенерированном коде, который имеет возвращаемый тип G_TYPE_NONE: g_signal_new (property-changed, G_TYPE_FROM_INTERFACE (iface), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (connmanManagerIface, property_changed), NULL, NULL, g_cclosure_marshal_generic, G_TYPE_NONE, 2 , G_TYPE_STRING, G_TYPE_VARIANT);   -  person Tyler Cox    schedule 08.02.2019
comment
Если я попытаюсь запустить: connman_manager_emit_property_changed(this->manager_proxy,test,g_variant_new_variant(g_variant_new_string(value))); Это также терпит неудачу, просто чтобы проверить, нет ли ничего странного в данных dbus.   -  person Tyler Cox    schedule 08.02.2019


Ответы (1)


ДОГАДАТЬСЯ!

В моем файле XML сигнал, за которым я слежу:

  <signal name="PropertyChanged">
     <arg name="name" type="s" />
     <arg name="value" type="v" />
  </signal>

И как бы я ни пытался понять, почему пример функции обратного вызова на freedesktop.org работает в обратном порядке, мне пришлось изменить следующее:

static void on_manager_properties_changed (
                       GDBusProxy          *proxy,
                       GVariant            *changed_properties,
                       const gchar* const  *invalidated_properties,
                       gpointer             user_data);

to:

static void on_manager_properties_changed (
                       GDBusProxy          *proxy,
                       const gchar* const  *invalidated_properties, //(name)
                       GVariant            *changed_properties, //(value)
                       gpointer             user_data);

Чтобы type='s' стоял перед type='v' в функции обратного вызова. После этого все было хорошо. Я думаю, что, возможно, какой бы сигнал ни наблюдал пример freedesktop, это мог быть другой элемент информации, чем то, к чему я стремился.

person Tyler Cox    schedule 08.02.2019
comment
Для справки: два метода уведомления о свойствах выглядят одинаково, но на самом деле реализованы совершенно по-разному. PropertyChanged является фактической частью Connman D-Bus API - это необходимо, потому что Connman вообще не поддерживает фактические свойства D-Bus (по историческим причинам IIRC). Пример кода, на который вы ссылаетесь, использует GDBusProxy::g-properties-changed, который использует свойства D-Bus. - person Jussi Kukkonen; 09.02.2019