mirror of
https://git.kernel.org/pub/scm/bluetooth/bluez.git
synced 2025-01-11 05:53:49 +08:00
Fix sink.c crash if removing device while connecting
This commit is contained in:
parent
6df133cba3
commit
9fe662df2a
11
audio/a2dp.c
11
audio/a2dp.c
@ -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);
|
||||
}
|
||||
|
||||
|
31
audio/sink.c
31
audio/sink.c
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user