2015-04-01 8 views
6

Non riesco a ricevere i segnali DBD systemd quando si utilizza il proxy manager generato da gdbus-codegen. Ma sono in grado di chiamare con successo i metodi forniti da systemd su DBus.Connessione a segnali DBD systemd tramite gdbus-codegen

Ho cercato online e ho guardato questi collegamenti senza molto successo. Non ci sono molti esempi su come farlo quando gdbus-codegen è usato per l'API systemd.

Ecco quello che ho fatto insieme a frammenti di codice.

1) Ho generato l'introspezione del sistema e ho usato quell'XML come input per gdbus-codegen.

... snip

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

... snip

2) scritto il mio codice del client per utilizzare le API C generati da GDBus-codegen e ha creato un proxy manager. (Tutto è sul bus di sistema).

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) Definire un gestore di segnale

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

4) Connesso un gestore di segnale a detto proxy per il segnale JobRemoved.

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

5) Utilizzato il proxy per avviare un servizio systemd. Ciò restituisce successo e ho potuto vedere l'unità avviare ed eseguire per un secondo o due e terminare.

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

6) systemd genera un segnale JobRemoved. dbus-monitor lo mostra.

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) Il gestore del segnale non viene mai chiamato. (Tutto utilizza il bus di sistema, non ci sono altri autobus). Ho provato varie stringhe per il parametro detailed_signal per g_signal_connect (come: JobRemoved, job_removed, ::job-removed, alcune non sono accettate da g_signal_connect).

Qualsiasi aiuto è molto apprezzato!

risposta

2

La soluzione era utilizzare un glib event loop nel mio programma. Il mio programma non aveva uno GMainLoop in esecuzione che era necessario per ottenere qualsiasi callback da glib. Questo non è un modo elegante ma per vari motivi ho deciso di generare un nuovo thread che poi bloccherebbe su g_main_loop_run. Ecco come sembra.

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 
} 

Inoltre, ho dovuto fissare la firma del gestore di segnale per essere compatibile con il segnale per ricevere parametri significativi.

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