Подключение к сигналам systemd DBUS с помощью gdbus-codegen

Я не могу получать сигналы systemd DBus при использовании прокси-сервера, сгенерированного gdbus-codegen. Но я могу успешно вызывать методы, предоставляемые systemd, через DBus.

Я искал в Интернете и смотрел эти ссылки без особого успеха. Не так много примеров того, как это сделать, когда gdbus-codegen используется для systemd API.

Вот что я сделал вместе с фрагментами кода.

1) Я сгенерировал интроспекцию systemd и использовал этот XML в качестве входных данных для gdbus-codegen.

... отрезать

<interface name="org.freedesktop.systemd1.Manager">
<signal name="JobRemoved">
<arg type="u"/> <arg type="o"/> <arg type="s"/> <arg type="s"/>
</signal>

... отрезать

2) Написал свой клиентский код для использования API-интерфейсов C, сгенерированных gdbus-codegen, и создал прокси-сервер менеджера. (Все на системной шине).

SystemdManager *systemdProxy = systemd_manager_proxy_new_for_bus_sync(
    G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE,
    "org.freedesktop.systemd1", "/org/freedesktop/systemd1",
    NULL, error);

3) Определите обработчик сигнала

static void on_done(GDBusProxy *proxy,
        gchar *sender_name,
        gchar *signal_name,
        GVariant *parameters,
        gpointer user_data)
{
    LOG_ERROR("on_done");
}

4) Подключил обработчик сигнала к этому прокси для сигнала JobRemoved.

if (g_signal_connect(systemdProxy, "job-removed",
                     G_CALLBACK(on_done), NULL) <= 0 )
{
    LOG_ERROR("Failed to connect to signal job-removed");
}

5) Использовал прокси для запуска службы systemd. Это возвращает успех, и я мог видеть, как модуль запускается и работает в течение секунды или двух и завершается.

ret = systemd_manager_call_start_unit_sync(
    systemdProxy, unit_name, unit_mode, &job_obj,
    NULL, &error);

6) systemd генерирует сигнал JobRemoved. dbus-monitor показывает это.

signal sender=:1.0 -> dest=(null destination) serial=11931
        path=/org/freedesktop/systemd1;
        interface=org.freedesktop.systemd1.Manager;
        member=JobRemoved
   uint32 7009
   object path "/org/freedesktop/systemd1/job/7009"
   string "mysample.service"
   string "done"

7) Мой обработчик сигналов никогда не вызывается. (Все использует системную шину, других шин нет). Я пробовал разные строки для detailed_signal 2-го параметра для g_signal_connect (например: JobRemoved, job_removed, ::job-removed, некоторые не принимаются g_signal_connect).

Любая помощь приветствуется!


person VJ-    schedule 01.04.2015    source источник
comment
Я столкнулся с той же проблемой, когда имя сигнала, требуемое в g_signal_connect, не соответствует файлу самоанализа XML. У меня был сигнал с именем TechnologyAdd, и мне пришлось использовать добавленную технологию. Мне кажется чистое племенное знание   -  person Joel Cunningham    schedule 28.03.2018


Ответы (1)


Решение состояло в том, чтобы использовать glib event loop в моей программе. В моей программе не было запущенного GMainLoop, необходимого для получения обратных вызовов от glib. Это не элегантный способ, но по разным причинам я решил создать новый поток, который затем заблокируется на g_main_loop_run. Вот как это выглядит.

void *event_loop_thread(void *unused) {
    GMainLoop *loop = g_main_loop_new(NULL, 0);
    g_main_loop_run(loop);
}
int main() {
    // snip
    pthread_create(&thread_id, NULL, event_loop_thread, NULL);
    // do steps 2 to 6, and at step 7 signal handler is called
}

Также мне пришлось исправить сигнатуру обработчика сигнала, чтобы она была совместима с сигналом для получения значимых параметров.

static void on_done(SystemdManager *manager,
        guint32 job_id,
        gchar *job_obj,
        gchar *unit_name,
        gchar *status)
{
    LOG_ERROR("on_done");
}
person VJ-    schedule 03.04.2015