Fix sink.c crash if removing device while connecting

This commit is contained in:
Johan Hedberg 2009-04-15 13:32:13 +03:00
parent 6df133cba3
commit 9fe662df2a
2 changed files with 30 additions and 12 deletions

View File

@ -78,6 +78,7 @@ struct a2dp_setup_cb {
};
struct a2dp_setup {
struct audio_device *dev;
struct avdtp *session;
struct a2dp_sep *sep;
struct avdtp_stream *stream;
@ -243,9 +244,8 @@ static struct a2dp_setup *find_setup_by_dev(struct audio_device *dev)
for (l = setups; l != NULL; l = l->next) {
struct a2dp_setup *setup = l->data;
struct audio_device *setup_dev = a2dp_get_dev(setup->session);
if (setup_dev == dev)
if (setup->dev == dev)
return setup;
}
@ -1220,6 +1220,8 @@ gboolean a2dp_source_cancel(struct audio_device *dev, unsigned int id)
struct a2dp_setup *setup;
GSList *l;
debug("a2dp_source_cancel()");
setup = find_setup_by_dev(dev);
if (!setup)
return FALSE;
@ -1234,7 +1236,7 @@ gboolean a2dp_source_cancel(struct audio_device *dev, unsigned int id)
}
if (!cb_data)
return FALSE;
error("a2dp_source_cancel: no matching callback with id %u", id);
setup->cb = g_slist_remove(setup->cb, cb_data);
g_free(cb_data);
@ -1328,6 +1330,7 @@ unsigned int a2dp_source_config(struct avdtp *session, struct a2dp_sep *sep,
if (!setup) {
setup = g_new0(struct a2dp_setup, 1);
setup->session = avdtp_ref(session);
setup->dev = a2dp_get_dev(session);
setups = g_slist_append(setups, setup);
}
@ -1412,6 +1415,7 @@ unsigned int a2dp_source_resume(struct avdtp *session, struct a2dp_sep *sep,
if (!setup) {
setup = g_new0(struct a2dp_setup, 1);
setup->session = avdtp_ref(session);
setup->dev = a2dp_get_dev(session);
setups = g_slist_append(setups, setup);
}
@ -1470,6 +1474,7 @@ unsigned int a2dp_source_suspend(struct avdtp *session, struct a2dp_sep *sep,
if (!setup) {
setup = g_new0(struct a2dp_setup, 1);
setup->session = avdtp_ref(session);
setup->dev = a2dp_get_dev(session);
setups = g_slist_append(setups, setup);
}

View File

@ -53,6 +53,7 @@ struct pending_request {
};
struct sink {
struct audio_device *dev;
struct avdtp *session;
struct avdtp_stream *stream;
unsigned int cb_id;
@ -146,12 +147,16 @@ static void avdtp_state_callback(struct audio_device *dev,
sink->session_state = new_state;
}
static void pending_request_free(struct pending_request *pending)
static void pending_request_free(struct audio_device *dev,
struct pending_request *pending)
{
if (pending->conn)
dbus_connection_unref(pending->conn);
if (pending->msg)
dbus_message_unref(pending->msg);
if (pending->id)
a2dp_source_cancel(dev, pending->id);
g_free(pending);
}
@ -179,7 +184,7 @@ static void stream_state_changed(struct avdtp_stream *stream,
reply = dbus_message_new_method_return(p->msg);
g_dbus_send_message(p->conn, reply);
pending_request_free(p);
pending_request_free(dev, p);
}
if (sink->session) {
@ -258,7 +263,7 @@ static gboolean stream_setup_retry(gpointer user_data)
}
sink->connect = NULL;
pending_request_free(pending);
pending_request_free(sink->dev, pending);
return FALSE;
}
@ -272,6 +277,8 @@ static void stream_setup_complete(struct avdtp *session, struct a2dp_sep *sep,
pending = sink->connect;
pending->id = 0;
if (stream) {
debug("Stream successfully created");
@ -282,7 +289,7 @@ static void stream_setup_complete(struct avdtp *session, struct a2dp_sep *sep,
}
sink->connect = NULL;
pending_request_free(pending);
pending_request_free(sink->dev, pending);
return;
}
@ -298,7 +305,7 @@ static void stream_setup_complete(struct avdtp *session, struct a2dp_sep *sep,
if (pending->msg)
error_failed(pending->conn, pending->msg, "Stream setup failed");
sink->connect = NULL;
pending_request_free(pending);
pending_request_free(sink->dev, pending);
debug("Stream setup failed : %s", avdtp_strerror(err));
}
}
@ -490,7 +497,7 @@ static void discovery_complete(struct avdtp *session, GSList *seps, struct avdtp
failed:
if (pending->msg)
error_failed(pending->conn, pending->msg, "Stream setup failed");
pending_request_free(pending);
pending_request_free(sink->dev, pending);
sink->connect = NULL;
avdtp_unref(sink->session);
sink->session = NULL;
@ -688,10 +695,10 @@ static void sink_free(struct audio_device *dev)
avdtp_unref(sink->session);
if (sink->connect)
pending_request_free(sink->connect);
pending_request_free(dev, sink->connect);
if (sink->disconnect)
pending_request_free(sink->disconnect);
pending_request_free(dev, sink->disconnect);
g_free(sink);
dev->sink = NULL;
@ -715,6 +722,8 @@ void sink_unregister(struct audio_device *dev)
struct sink *sink_init(struct audio_device *dev)
{
struct sink *sink;
if (!g_dbus_register_interface(dev->conn, dev->path,
AUDIO_SINK_INTERFACE,
sink_methods, sink_signals, NULL,
@ -728,7 +737,11 @@ struct sink *sink_init(struct audio_device *dev)
avdtp_callback_id = avdtp_add_state_cb(avdtp_state_callback,
NULL);
return g_new0(struct sink, 1);
sink = g_new0(struct sink, 1);
sink->dev = dev;
return sink;
}
gboolean sink_is_active(struct audio_device *dev)