Fix blocking service watch initial connect handling

This commit is contained in:
Marcel Holtmann 2009-08-06 22:10:19 -07:00
parent 572a89cce2
commit 2520e26820
3 changed files with 96 additions and 46 deletions

View File

@ -43,8 +43,6 @@ DBusConnection *g_dbus_setup_bus(DBusBusType type, const char *name,
gboolean g_dbus_request_name(DBusConnection *connection, const char *name,
DBusError *error);
gboolean g_dbus_check_service(DBusConnection *connection, const char *name);
gboolean g_dbus_set_disconnect_function(DBusConnection *connection,
GDBusWatchFunction function,
void *user_data, DBusFreeFunction destroy);

View File

@ -281,49 +281,6 @@ gboolean g_dbus_request_name(DBusConnection *connection, const char *name,
return TRUE;
}
gboolean g_dbus_check_service(DBusConnection *connection, const char *name)
{
DBusMessage *message, *reply;
const char **names;
int i, count;
gboolean result = FALSE;
message = dbus_message_new_method_call(DBUS_SERVICE_DBUS,
DBUS_PATH_DBUS, DBUS_INTERFACE_DBUS, "ListNames");
if (message == NULL) {
error("Can't allocate new message");
return FALSE;
}
reply = dbus_connection_send_with_reply_and_block(connection,
message, -1, NULL);
dbus_message_unref(message);
if (reply == NULL) {
error("Failed to execute method call");
return FALSE;
}
if (dbus_message_get_args(reply, NULL,
DBUS_TYPE_ARRAY, DBUS_TYPE_STRING,
&names, &count, DBUS_TYPE_INVALID) == FALSE) {
error("Failed to read name list");
goto done;
}
for (i = 0; i < count; i++)
if (g_str_equal(names[i], name) == TRUE) {
result = TRUE;
break;
}
done:
dbus_message_unref(reply);
return result;
}
gboolean g_dbus_set_disconnect_function(DBusConnection *connection,
GDBusWatchFunction function,
void *user_data, DBusFreeFunction destroy)

View File

@ -307,6 +307,97 @@ static DBusHandlerResult name_exit_filter(DBusConnection *connection,
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
}
struct service_data {
DBusConnection *conn;
const char *name;
GDBusWatchFunction conn_func;
void *user_data;
};
static void service_reply(DBusPendingCall *call, void *user_data)
{
struct service_data *data = user_data;
DBusMessage *reply;
DBusError error;
char **names;
int i, count;
reply = dbus_pending_call_steal_reply(call);
if (reply == NULL)
return;
dbus_error_init(&error);
if (dbus_message_get_args(reply, &error,
DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &names, &count,
DBUS_TYPE_INVALID) == FALSE) {
if (dbus_error_is_set(&error) == TRUE) {
error("%s", error.message);
dbus_error_free(&error);
} else {
error("Wrong arguments for name list");
}
goto done;
}
for (i = 0; i < count; i++)
if (g_strcmp0(names[i], data->name) == 0) {
if (data->conn_func)
data->conn_func(data->conn, data->user_data);
break;
}
g_strfreev(names);
done:
dbus_message_unref(reply);
}
static void check_service(DBusConnection *connection, const char *name,
GDBusWatchFunction connect, void *user_data)
{
DBusMessage *message;
DBusPendingCall *call;
struct service_data *data;
data = g_try_malloc0(sizeof(*data));
if (data == NULL) {
error("Can't allocate data structure");
return;
}
data->conn = connection;
data->name = name;
data->conn_func = connect;
data->user_data = user_data;
message = dbus_message_new_method_call(DBUS_SERVICE_DBUS,
DBUS_PATH_DBUS, DBUS_INTERFACE_DBUS, "ListNames");
if (message == NULL) {
error("Can't allocate new message");
g_free(data);
return;
}
if (dbus_connection_send_with_reply(connection, message,
&call, -1) == FALSE) {
error("Failed to execute method call");
g_free(data);
goto done;
}
if (call == NULL) {
error("D-Bus connection not available");
g_free(data);
goto done;
}
dbus_pending_call_set_notify(call, service_reply, data, NULL);
done:
dbus_message_unref(message);
}
guint g_dbus_add_service_watch(DBusConnection *connection, const char *name,
GDBusWatchFunction connect,
GDBusWatchFunction disconnect,
@ -328,7 +419,7 @@ guint g_dbus_add_service_watch(DBusConnection *connection, const char *name,
/* The filter is already added if this is not the first callback
* registration for the name */
if (!first)
return listener_id;
goto done;
if (name) {
debug("name_listener_add(%s)", name);
@ -339,6 +430,10 @@ guint g_dbus_add_service_watch(DBusConnection *connection, const char *name,
}
}
done:
if (connect)
check_service(connection, name, connect, user_data);
return listener_id;
}