diff options
author | David Zeuthen <davidz@redhat.com> | 2010-06-17 14:47:31 -0400 |
---|---|---|
committer | David Zeuthen <davidz@redhat.com> | 2010-06-17 14:47:31 -0400 |
commit | 427d3c5ea1f4af5d1f26f70ffae5606eb0a70618 (patch) | |
tree | e92b7bfaebfa7b10ceefb2c2a047cac67b8b7eac | |
parent | 5700b0c08cd5c37097af442d784c489e88e24cb5 (diff) |
Handle signals
-rw-r--r-- | src/gdbusgi.c | 411 | ||||
-rw-r--r-- | src/myfrobnicator.c | 69 | ||||
-rw-r--r-- | src/myfrobnicator.h | 7 | ||||
-rw-r--r-- | src/test.c | 118 |
4 files changed, 544 insertions, 61 deletions
diff --git a/src/gdbusgi.c b/src/gdbusgi.c index f34270a..04a1512 100644 --- a/src/gdbusgi.c +++ b/src/gdbusgi.c @@ -1024,19 +1024,26 @@ convert_gvariant_to_gi (GVariant *variant, typedef struct { GObject *object; + gchar *object_path; + GDBusConnection *connection; GDBusInterfaceInfo *info; gpointer user_data; GDestroyNotify user_data_free_func; GHashTable *dbus_method_name_to_method_data; + GHashTable *g_signal_name_to_signal_data; } ExportData; static void export_data_free (ExportData *data) { g_hash_table_unref (data->dbus_method_name_to_method_data); + g_hash_table_unref (data->g_signal_name_to_signal_data); if (data->object != NULL) g_object_unref (data->object); + g_free (data->object_path); + if (data->connection != NULL) + g_object_unref (data->connection); if (data->info != NULL) g_dbus_interface_info_unref (data->info); if (data->user_data_free_func != NULL) @@ -1047,19 +1054,6 @@ export_data_free (ExportData *data) /* ---------------------------------------------------------------------------------------------------- */ typedef struct _ArgData ArgData; - -typedef struct -{ - GIFunctionInfo *method; - GDBusMethodInfo *dbus_method; - - guint num_in_args; /* number of GIArgInfo where direction is IN or IN_OUT */ - guint num_out_args; /* number of GIArgInfo where direction is OUT or IN_OUT */ - - GPtrArray *args; - ArgData *return_value; -} MethodData; - struct _ArgData { GIDirection direction; @@ -1101,20 +1095,6 @@ arg_data_free (ArgData *data) g_free (data); } -static void -method_data_free (MethodData *data) -{ - g_base_info_unref (data->method); - if (data->dbus_method != NULL) - g_dbus_method_info_unref (data->dbus_method); - g_ptr_array_unref (data->args); - if (data->return_value != NULL) - arg_data_free (data->return_value); - g_free (data); -} - -/* ---------------------------------------------------------------------------------------------------- */ - static gchar * arg_data_print (ArgData *data) { @@ -1145,6 +1125,32 @@ arg_data_print (ArgData *data) return g_string_free (str, FALSE); } +/* ---------------------------------------------------------------------------------------------------- */ + +typedef struct +{ + GIFunctionInfo *method; + GDBusMethodInfo *dbus_method; + + guint num_in_args; /* number of GIArgInfo where direction is IN or IN_OUT */ + guint num_out_args; /* number of GIArgInfo where direction is OUT or IN_OUT */ + + GPtrArray *args; + ArgData *return_value; +} MethodData; + +static void +method_data_free (MethodData *data) +{ + g_base_info_unref (data->method); + if (data->dbus_method != NULL) + g_dbus_method_info_unref (data->dbus_method); + g_ptr_array_unref (data->args); + if (data->return_value != NULL) + arg_data_free (data->return_value); + g_free (data); +} + static gchar * method_data_print (MethodData *data, guint indent) @@ -1206,6 +1212,69 @@ method_data_dump (MethodData *data, gchar *s; s = method_data_print (data, indent); g_print ("------------------------------------------------------------------------\n" + "METHOD:\n" + "%s" + "------------------------------------------------------------------------\n", + s); + g_free (s); +} + +/* ---------------------------------------------------------------------------------------------------- */ + +typedef struct +{ + GISignalInfo *signal; + GDBusSignalInfo *dbus_signal; + + /* all args in the in direction and return values are not supported */ + GPtrArray *args; +} SignalData; + +static void +signal_data_free (SignalData *data) +{ + g_base_info_unref (data->signal); + if (data->dbus_signal != NULL) + g_dbus_signal_info_unref (data->dbus_signal); + g_ptr_array_unref (data->args); + g_free (data); +} + +static gchar * +signal_data_print (SignalData *data, + guint indent) +{ + GString *str; + guint n; + gchar *s; + + str = g_string_new (NULL); + g_string_append_printf (str, + "%*sName: %s\n" + "%*sD-Bus name: %s\n", + indent, "", g_base_info_get_name ((GIBaseInfo *) data->signal), + indent, "", data->dbus_signal->name); + for (n = 0; n < data->args->len; n++) + { + ArgData *ad = data->args->pdata[n]; + s = arg_data_print (ad); + g_string_append_printf (str, + "%*s arg[%2d]: %s\n", + indent, "", n, s); + g_free (s); + } + + return g_string_free (str, FALSE); +} + +static void +signal_data_dump (SignalData *data, + guint indent) +{ + gchar *s; + s = signal_data_print (data, indent); + g_print ("------------------------------------------------------------------------\n" + "SIGNAL:\n" "%s" "------------------------------------------------------------------------\n", s); @@ -1893,16 +1962,138 @@ get_method_data (GIFunctionInfo *method, return ret; } +/* ---------------------------------------------------------------------------------------------------- */ + +static SignalData * +get_signal_data (GISignalInfo *signal, + const gchar *dbus_name, + GError **error) +{ + SignalData *ret; + GICallableInfo *callable; + GPtrArray *dbus_args; + ArgData *ad; + guint n; + + dbus_args = g_ptr_array_new (); + + ret = g_new0 (SignalData, 1); + ret->signal = g_base_info_ref ((GIBaseInfo *) signal); + ret->args = g_ptr_array_new_with_free_func ((GDestroyNotify) arg_data_free); + + /* this/self */ + ad = arg_data_new (); + ad->direction = GI_DIRECTION_IN; + g_ptr_array_add (ret->args, ad); + + callable = (GICallableInfo *) signal; + + g_print ("Using dbus name `%s' for signal `%s'\n", dbus_name, g_base_info_get_name ((GIBaseInfo *) signal)); + + /* TODO: reject if it has a return value */ + + /* Go through all parameters */ + for (n = 0; n < (guint) g_callable_info_get_n_args (callable); n++) + { + GIArgInfo *arg; + GITypeInfo *type; + GDBusArgInfo *arg_info; + gboolean not_on_dbus; + guint m; + + /* TODO: reject out and inout params */ + + /* Don't export arg on D-Bus if it's used for another arg (e.g. a length parameter for an array) */ + not_on_dbus = FALSE; + + arg = g_callable_info_get_arg (callable, n); + type = g_arg_info_get_type (arg); + + ad = arg_data_new (); + ad->direction = g_arg_info_get_direction (arg); + ad->arg_info = g_base_info_ref ((GIBaseInfo *) arg); + ad->type_info = g_arg_info_get_type (arg); + ad->transfer = g_arg_info_get_ownership_transfer (arg); + + /* Now figure out if this arg is a length param for an array */ + for (m = 0; m < (guint) g_callable_info_get_n_args (callable) && !not_on_dbus; m++) + { + /* TODO: also check return value! */ + GIArgInfo *other_arg; + GITypeInfo *other_type; + other_arg = g_callable_info_get_arg (callable, m); + other_type = g_arg_info_get_type (other_arg); + /* get_array_length() assumes first arg is this/self */ + if (g_type_info_get_array_length (other_type) == (gint) n + 1) + { + not_on_dbus = TRUE; + ad->is_array_len_for_position = n; + } + g_base_info_unref ((GIBaseInfo *) other_type); + g_base_info_unref ((GIBaseInfo *) other_arg); + } + + /* Set if this is an array using another arg as a length parameter */ + ad->array_len_position = g_type_info_get_array_length (type); + + arg_info = NULL; + if (!not_on_dbus) + { + arg_info = get_arg_info (callable, arg, error); + if (arg_info == NULL) + { + g_prefix_error (error, + "Error processing argument `%s' of signal `%s': ", + g_base_info_get_name ((GIBaseInfo *) arg), + g_base_info_get_name ((GIBaseInfo *) signal)); + g_base_info_unref ((GIBaseInfo *) arg); + g_base_info_unref ((GIBaseInfo *) type); + signal_data_free (ret); + ret = NULL; + goto out; + } + } + + ad->dbus_arg_info = arg_info != NULL ? g_dbus_arg_info_ref (arg_info) : NULL; + + if (arg_info != NULL) + g_ptr_array_add (dbus_args, arg_info); + g_ptr_array_add (ret->args, ad); + + if (arg_info != NULL) + g_dbus_arg_info_unref (arg_info); + g_base_info_unref ((GIBaseInfo *) arg); + g_base_info_unref ((GIBaseInfo *) type); + } + g_ptr_array_add (dbus_args, NULL); + + ret->dbus_signal = g_new0 (GDBusSignalInfo, 1); + ret->dbus_signal->ref_count = 1; + ret->dbus_signal->name = g_strdup (dbus_name); + g_ptr_array_ref (dbus_args); + ret->dbus_signal->args = (GDBusArgInfo **) g_ptr_array_free (dbus_args, FALSE); + + out: + g_ptr_array_foreach (dbus_args, (GFunc) g_dbus_arg_info_unref, NULL); + g_ptr_array_unref (dbus_args); + return ret; +} + +/* ---------------------------------------------------------------------------------------------------- */ + static GDBusInterfaceInfo * compute_introspection_data (GObject *object, ExportData *data, GError **error) { + GPtrArray *signal_infos; GPtrArray *method_infos; GDBusInterfaceInfo *ret; GIRepository *repo; GIBaseInfo *info; guint n; + guint n_methods; + guint n_signals; ret = NULL; info = NULL; @@ -1937,7 +2128,8 @@ compute_introspection_data (GObject *object, g_assert (GI_IS_OBJECT_INFO (info)); method_infos = g_ptr_array_new (); - for (n = 0; n < (guint) g_object_info_get_n_methods ((GIObjectInfo *) info); n++) + n_methods = g_object_info_get_n_methods ((GIObjectInfo *) info); + for (n = 0; n < n_methods; n++) { GIFunctionInfo *method; const gchar *dbus_name; @@ -1967,10 +2159,48 @@ compute_introspection_data (GObject *object, g_strdup (dbus_name), method_data); } + g_base_info_unref ((GIBaseInfo *) method); } g_ptr_array_add (method_infos, NULL); ret->methods = (GDBusMethodInfo **) g_ptr_array_free (method_infos, FALSE); + signal_infos = g_ptr_array_new (); + n_signals = g_object_info_get_n_signals ((GIObjectInfo *) info); + for (n = 0; n < n_signals; n++) + { + GISignalInfo *signal; + const gchar *dbus_name; + + signal = g_object_info_get_signal ((GIObjectInfo *) info, n); + dbus_name = g_base_info_get_attribute ((GIBaseInfo *) signal, "gdbus.signal"); + if (dbus_name != NULL) + { + SignalData *signal_data; + + signal_data = get_signal_data (signal, + dbus_name, + error); + if (signal_data == NULL) + { + g_ptr_array_foreach (signal_infos, (GFunc) g_dbus_signal_info_unref, NULL); + g_ptr_array_unref (signal_infos); + g_dbus_interface_info_unref (ret); + ret = NULL; + goto out; + } + g_ptr_array_add (signal_infos, signal_data->dbus_signal); + + signal_data_dump (signal_data, 0); + + g_hash_table_insert (data->g_signal_name_to_signal_data, + g_strdup (g_base_info_get_name ((GIBaseInfo *) signal_data->signal)), + signal_data); + } + g_base_info_unref ((GIBaseInfo *) signal); + } + g_ptr_array_add (signal_infos, NULL); + ret->signals = (GDBusSignalInfo **) g_ptr_array_free (signal_infos, FALSE); + out: if (info != NULL) g_base_info_unref (info); @@ -1979,6 +2209,104 @@ compute_introspection_data (GObject *object, /* ---------------------------------------------------------------------------------------------------- */ +typedef struct +{ + GClosure parent_instance; + + gulong signal_handler_id; + SignalData *signal_data; + ExportData *export_data; +} GDBusClosure; + +static GVariant * +process_signal_args (guint n_param_values, + const GValue *param_values, + SignalData *data) +{ + guint n; + ArgData *ad; + GVariant *value; + GVariantType *gvariant_type; + GVariantBuilder builder; + GArgument *array_len_arg; + GITypeInfo *array_len_arg_type; + GArgument **args; + + g_assert_cmpint (n_param_values, ==, data->args->len); + + /* Convert GValue to GArgument + * + * TODO: verify that the conversion really is that simple... + */ + args = g_new0 (GArgument *, n_param_values); + for (n = 0; n < n_param_values; n++) + args[n] = (GArgument *) &(param_values[n].data[0]); + + g_variant_builder_init (&builder, G_VARIANT_TYPE_TUPLE); + for (n = 0; n < data->args->len; n++) + { + ad = data->args->pdata[n]; + + if (ad->dbus_arg_info == NULL) + continue; + + array_len_arg = NULL; + array_len_arg_type = NULL; + if (ad->array_len_position != -1) + { + array_len_arg = args[ad->array_len_position]; + array_len_arg_type = ((ArgData *) data->args->pdata[ad->array_len_position])->type_info; + } + + gvariant_type = g_variant_type_new (ad->dbus_arg_info->signature); + value = convert_gi_to_gvariant (args[n], + ad->type_info, + gvariant_type, + array_len_arg, + array_len_arg_type); + g_variant_ref_sink (value); + g_variant_builder_add_value (&builder, value); + g_variant_unref (value); + g_variant_type_free (gvariant_type); + } + + g_free (args); + + return g_variant_builder_end (&builder); +} + +static void +marshal_signal_onto_dbus (GClosure *_closure, + GValue *return_value, + guint n_param_values, + const GValue *param_values, + gpointer invocation_hint, + gpointer marshal_data) +{ + GDBusClosure *closure = (GDBusClosure *) _closure; + GVariant *variant; + GError *error; + + variant = process_signal_args (n_param_values, + param_values, + closure->signal_data); + error = NULL; + if (!g_dbus_connection_emit_signal (closure->export_data->connection, + NULL, + closure->export_data->object_path, + closure->export_data->info->name, + closure->signal_data->dbus_signal->name, + variant, + &error)) + { + g_warning ("Error emitting D-Bus signal `%s' in response to G signal: %s", + closure->signal_data->dbus_signal->name, + error->message); + g_error_free (error); + } + g_variant_unref (variant); +} + guint g_dbus_connection_register_gobject (GDBusConnection *connection, GObject *object, @@ -1996,6 +2324,8 @@ g_dbus_connection_register_gobject (GDBusConnection *connection, data = g_new0 (ExportData, 1); data->object = g_object_ref (object); + data->object_path = g_strdup (object_path); + data->connection = g_object_ref (connection); data->user_data = user_data; data->user_data_free_func = user_data_free_func; @@ -2003,6 +2333,10 @@ g_dbus_connection_register_gobject (GDBusConnection *connection, g_str_equal, g_free, (GDestroyNotify) method_data_free); + data->g_signal_name_to_signal_data = g_hash_table_new_full (g_str_hash, + g_str_equal, + g_free, + (GDestroyNotify) signal_data_free); data->info = compute_introspection_data (object, data, @@ -2010,6 +2344,27 @@ g_dbus_connection_register_gobject (GDBusConnection *connection, if (data->info == NULL) goto fail; + /* Set up signal handlers for all exported signals */ + GHashTableIter iter; + const gchar *g_signal_name; + SignalData *signal_data; + g_hash_table_iter_init (&iter, data->g_signal_name_to_signal_data); + while (g_hash_table_iter_next (&iter, (gpointer*) &g_signal_name, (gpointer*) &signal_data)) + { + GDBusClosure *closure; + + closure = (GDBusClosure *) g_closure_new_simple (sizeof (GDBusClosure), NULL); + g_closure_set_marshal ((GClosure *) closure, marshal_signal_onto_dbus); + + closure->signal_data = signal_data; + closure->signal_handler_id = g_signal_connect_closure (object, + g_signal_name, + (GClosure *) closure, + TRUE); + closure->export_data = data; + /* TODO: we need to unregister these handlers in export_data_free() */ + } + return g_dbus_connection_register_object (connection, object_path, data->info, diff --git a/src/myfrobnicator.c b/src/myfrobnicator.c index 49c0cfd..9936e62 100644 --- a/src/myfrobnicator.c +++ b/src/myfrobnicator.c @@ -32,6 +32,14 @@ struct _MyFrobnicatorPrivate guint foo; }; +enum +{ + LASER_FIRED_SIGNAL, + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL] = {0}; + G_DEFINE_TYPE (MyFrobnicator, my_frobnicator, G_TYPE_OBJECT); static void @@ -42,6 +50,31 @@ my_frobnicator_init (MyFrobnicator *frobnicator) static void my_frobnicator_class_init (MyFrobnicatorClass *klass) { + /** + * MyFrobnicator::laser-fired: + * @frobnicator: A #MyFrobnicator. + * @str: A string. + * @carray_as: (array) (element-type utf8): + * @garray_ai: (array zero-terminated="0") (element-type gint): + * + * Check that signal parameters are marshalled correctly onto the + * bus. Btw, Hmm, apparently (array length=carray_ai_len) doesn't + * work yet. TODO: file bug + * + * Attributes: (gdbus.signal LaserFired) + */ + signals[LASER_FIRED_SIGNAL] = g_signal_new ("laser-fired", + MY_TYPE_FROBNICATOR, + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (MyFrobnicatorClass, laser_fired), + NULL, /* accumulator */ + NULL, /* accu_data */ + NULL, /* we don't need a C marshaller if we're only using D-Bus */ + G_TYPE_NONE, + 3, + G_TYPE_STRING, + G_TYPE_STRV, + G_TYPE_ARRAY); } MyFrobnicator * @@ -406,3 +439,39 @@ my_frobnicator_return_arrays (MyFrobnicator *frobnicator, as[2] = g_strdup ("0.03"); *out_carray_as = as; } + +/** + * my_frobnicator_fire_laser: + * @frobnicator: + * + * Emits the laser-fired signal. + * + * Attributes: (gdbus.method FireLaser) + */ +void +my_frobnicator_fire_laser (MyFrobnicator *frobnicator) +{ + const gchar *strv[4]; + GArray *garray_ai; + + strv[0] = "zero"; + strv[1] = "two"; + strv[2] = "three"; + strv[3] = NULL; + + garray_ai = g_array_new (FALSE, FALSE, sizeof (gint)); + g_array_set_size (garray_ai, 3); + ((gint *) (garray_ai)->data)[0] = 10; + ((gint *) (garray_ai)->data)[1] = 20; + ((gint *) (garray_ai)->data)[2] = 30; + + g_signal_emit (frobnicator, + signals[LASER_FIRED_SIGNAL], + 0, + "woot", + strv, + garray_ai); + + g_array_unref (garray_ai); +} + diff --git a/src/myfrobnicator.h b/src/myfrobnicator.h index ea9ab42..b299b69 100644 --- a/src/myfrobnicator.h +++ b/src/myfrobnicator.h @@ -62,6 +62,11 @@ struct _MyFrobnicatorClass { /*< private >*/ GObjectClass parent_class; + + void (*laser_fired) (MyFrobnicator *frobnicator, + const gchar *str, + const gchar *const *carray_as, + GArray *garray_ai); }; GType my_frobnicator_get_type (void) G_GNUC_CONST; @@ -128,6 +133,8 @@ void my_frobnicator_return_arrays (MyFrobnicator *frobnicator, gchar ***out_carray_as_nzt, gchar ***out_carray_as); +void my_frobnicator_fire_laser (MyFrobnicator *frobnicator); + G_END_DECLS #endif /* __MY_FROBNICATOR_H__ */ @@ -31,6 +31,7 @@ #include "myfrobnicator.h" static GMainLoop *loop; +static GMainLoop *thread_loop; static MyFrobnicator *obj; static gboolean just_serve = FALSE; @@ -53,6 +54,20 @@ on_bus_acquired (GDBusConnection *connection, } static void +run_tests_on_signal_received (GDBusConnection *connection, + const gchar *sender_name, + const gchar *object_path, + const gchar *interface_name, + const gchar *signal_name, + GVariant *parameters, + gpointer user_data) +{ + GVariant **signal_params = user_data; + *signal_params = g_variant_ref (parameters); + g_main_loop_quit (thread_loop); +} + +static void run_test (GDBusConnection *connection) { GError *error; @@ -209,45 +224,41 @@ run_test (GDBusConnection *connection) "org.MyProject.Frobnicator", "SimpleTypes", g_variant_new ("(bnqiuxtiudsog)", - TRUE, 10, 11, 12, 13, G_GINT64_CONSTANT (14), G_GUINT64_CONSTANT (15), 16, 17, 18.5, - "a string", "/the/path", "assgit"), + TRUE, + 10, + 11, + 12, + 13, + G_GINT64_CONSTANT (14), + G_GUINT64_CONSTANT (15), + 16, + 17, + 18.5, + "a string", + "/the/path", + "assgit"), G_VARIANT_TYPE ("(bnqiuxtiudsog)"), G_DBUS_CALL_FLAGS_NONE, -1, NULL, /* GCancellable */ &error); g_assert_no_error (error); - { - gboolean v_boolean; - gint16 v_int16; - guint16 v_uint16; - gint32 v_int32; - guint32 v_uint32; - gint64 v_int64; - guint64 v_uint64; - gint v_int; - guint v_uint; - gdouble v_double; - const gchar *v_string; - const gchar *v_object_path; - const gchar *v_signature; - g_variant_get (ret, - "(bnqiuxtiud&s&o&g)", - &v_boolean, &v_int16, &v_uint16, &v_int32, &v_uint32, - &v_int64, &v_uint64, &v_int, &v_uint, &v_double, - &v_string, &v_object_path, &v_signature); - g_assert (!!v_boolean == !TRUE); - g_assert_cmpint (v_int16, ==, 10 + 100); - g_assert_cmpint (v_uint16, ==, 11 + 101); - g_assert_cmpint (v_int32, ==, 12 + 102); - g_assert_cmpint (v_uint32, ==, 13 + 103); - g_assert_cmpint (v_int64, ==, 14 + 104); - g_assert_cmpint (v_uint64, ==, 15 + 105); - g_assert_cmpint (v_int, ==, 16 + 106); - g_assert_cmpint (v_uint, ==, 17 + 107); - g_assert_cmpint (v_double, ==, 18.5 + 108); - } + other = g_variant_new_parsed ("(false, " + "int16 110, " + "uint16 112, " + "114, " + "uint32 116, " + "int64 118, " + "uint64 120, " + "122, " + "uint32 124, " + "126.5, " + "\"You passed `a string'\", " + "objectpath '/you/passed/the/path', " + "signature 'assgitassgit')"); + g_assert (g_variant_equal (ret, other)); g_variant_unref (ret); + g_variant_unref (other); error = NULL; ret = g_dbus_connection_call_sync (connection, @@ -295,6 +306,48 @@ run_test (GDBusConnection *connection) g_assert (g_variant_equal (ret, other)); g_variant_unref (ret); g_variant_unref (other); + + guint signal_sub_id; + GVariant *signal_params; + signal_sub_id = g_dbus_connection_signal_subscribe (connection, + NULL, /* sender */ + "org.MyProject.Frobnicator", + "LaserFired", + "/org/My/Frobnicator", + NULL, /* arg0 */ + run_tests_on_signal_received, + &signal_params, + NULL); /* user_data_free_func */ + g_assert (signal_sub_id > 0); + + error = NULL; + signal_params = NULL; + ret = g_dbus_connection_call_sync (connection, + "org.My.Service", + "/org/My/Frobnicator", + "org.MyProject.Frobnicator", + "FireLaser", + NULL, + G_VARIANT_TYPE ("()"), + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, /* GCancellable */ + &error); + g_assert_no_error (error); + g_variant_unref (ret); + g_assert (signal_params == NULL); + + g_main_loop_run (thread_loop); + g_assert (signal_params != NULL); + + other = g_variant_new_parsed ("('woot', " + "['zero', 'two', 'three'], " + "[10, 20, 30])"); + g_assert (g_variant_equal (signal_params, other)); + g_variant_unref (signal_params); + g_variant_unref (other); + + g_dbus_connection_signal_unsubscribe (connection, signal_sub_id); } static gpointer @@ -302,7 +355,6 @@ run_test_thread_func (gpointer user_data) { GDBusConnection *connection = G_DBUS_CONNECTION (user_data); GMainContext *thread_context; - GMainLoop *thread_loop; thread_context = g_main_context_new (); thread_loop = g_main_loop_new (thread_context, FALSE); |