mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-12-16 08:56:45 -05:00
bluez5: setting this->transport = NULL should block data thread
Since the data thread accesses the spa_bt_transport, its destroy event needs to sync with data thread to avoid races. Also check transport is present in places that need it.
This commit is contained in:
parent
a5e52c07b1
commit
da2fa8a599
4 changed files with 61 additions and 4 deletions
|
|
@ -596,6 +596,9 @@ static void a2dp_on_timeout(struct spa_source *source)
|
||||||
struct spa_io_buffers *io = port->io;
|
struct spa_io_buffers *io = port->io;
|
||||||
uint64_t prev_time, now_time;
|
uint64_t prev_time, now_time;
|
||||||
|
|
||||||
|
if (this->transport == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
if (this->started && spa_system_timerfd_read(this->data_system, this->timerfd, &exp) < 0)
|
if (this->started && spa_system_timerfd_read(this->data_system, this->timerfd, &exp) < 0)
|
||||||
spa_log_warn(this->log, "error reading timerfd: %s", strerror(errno));
|
spa_log_warn(this->log, "error reading timerfd: %s", strerror(errno));
|
||||||
|
|
||||||
|
|
@ -1221,11 +1224,23 @@ static const struct spa_node_methods impl_node = {
|
||||||
.process = impl_node_process,
|
.process = impl_node_process,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static int do_transport_destroy(struct spa_loop *loop,
|
||||||
|
bool async,
|
||||||
|
uint32_t seq,
|
||||||
|
const void *data,
|
||||||
|
size_t size,
|
||||||
|
void *user_data)
|
||||||
|
{
|
||||||
|
struct impl *this = user_data;
|
||||||
|
this->transport = NULL;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static void transport_destroy(void *data)
|
static void transport_destroy(void *data)
|
||||||
{
|
{
|
||||||
struct impl *this = data;
|
struct impl *this = data;
|
||||||
spa_log_debug(this->log, "transport %p destroy", this->transport);
|
spa_log_debug(this->log, "transport %p destroy", this->transport);
|
||||||
this->transport = NULL;
|
spa_loop_invoke(this->data_loop, do_transport_destroy, 0, NULL, 0, true, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct spa_bt_transport_events transport_events = {
|
static const struct spa_bt_transport_events transport_events = {
|
||||||
|
|
|
||||||
|
|
@ -1092,11 +1092,23 @@ static const struct spa_node_methods impl_node = {
|
||||||
.process = impl_node_process,
|
.process = impl_node_process,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static int do_transport_destroy(struct spa_loop *loop,
|
||||||
|
bool async,
|
||||||
|
uint32_t seq,
|
||||||
|
const void *data,
|
||||||
|
size_t size,
|
||||||
|
void *user_data)
|
||||||
|
{
|
||||||
|
struct impl *this = user_data;
|
||||||
|
this->transport = NULL;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static void transport_destroy(void *data)
|
static void transport_destroy(void *data)
|
||||||
{
|
{
|
||||||
struct impl *this = data;
|
struct impl *this = data;
|
||||||
spa_log_debug(this->log, "transport %p destroy", this->transport);
|
spa_log_debug(this->log, "transport %p destroy", this->transport);
|
||||||
this->transport = NULL;
|
spa_loop_invoke(this->data_loop, do_transport_destroy, 0, NULL, 0, true, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void transport_state_changed(void *data, enum spa_bt_transport_state old,
|
static void transport_state_changed(void *data, enum spa_bt_transport_state old,
|
||||||
|
|
|
||||||
|
|
@ -315,6 +315,9 @@ static void flush_data(struct impl *this)
|
||||||
uint32_t min_in_size;
|
uint32_t min_in_size;
|
||||||
uint8_t *packet;
|
uint8_t *packet;
|
||||||
|
|
||||||
|
if (this->transport == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
/* get buffer */
|
/* get buffer */
|
||||||
if (!port->current_buffer) {
|
if (!port->current_buffer) {
|
||||||
spa_return_if_fail(!spa_list_is_empty(&port->ready));
|
spa_return_if_fail(!spa_list_is_empty(&port->ready));
|
||||||
|
|
@ -445,6 +448,9 @@ static void sco_on_timeout(struct spa_source *source)
|
||||||
struct port *port = &this->port;
|
struct port *port = &this->port;
|
||||||
uint64_t exp;
|
uint64_t exp;
|
||||||
|
|
||||||
|
if (this->transport == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
/* Read the timerfd */
|
/* Read the timerfd */
|
||||||
if (this->started && spa_system_timerfd_read(this->data_system, this->timerfd, &exp) < 0)
|
if (this->started && spa_system_timerfd_read(this->data_system, this->timerfd, &exp) < 0)
|
||||||
spa_log_warn(this->log, "error reading timerfd: %s", strerror(errno));
|
spa_log_warn(this->log, "error reading timerfd: %s", strerror(errno));
|
||||||
|
|
@ -1049,11 +1055,23 @@ static const struct spa_node_methods impl_node = {
|
||||||
.process = impl_node_process,
|
.process = impl_node_process,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static int do_transport_destroy(struct spa_loop *loop,
|
||||||
|
bool async,
|
||||||
|
uint32_t seq,
|
||||||
|
const void *data,
|
||||||
|
size_t size,
|
||||||
|
void *user_data)
|
||||||
|
{
|
||||||
|
struct impl *this = user_data;
|
||||||
|
this->transport = NULL;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static void transport_destroy(void *data)
|
static void transport_destroy(void *data)
|
||||||
{
|
{
|
||||||
struct impl *this = data;
|
struct impl *this = data;
|
||||||
spa_log_debug(this->log, "transport %p destroy", this->transport);
|
spa_log_debug(this->log, "transport %p destroy", this->transport);
|
||||||
this->transport = NULL;
|
spa_loop_invoke(this->data_loop, do_transport_destroy, 0, NULL, 0, true, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct spa_bt_transport_events transport_events = {
|
static const struct spa_bt_transport_events transport_events = {
|
||||||
|
|
|
||||||
|
|
@ -1068,11 +1068,23 @@ static const struct spa_node_methods impl_node = {
|
||||||
.process = impl_node_process,
|
.process = impl_node_process,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static int do_transport_destroy(struct spa_loop *loop,
|
||||||
|
bool async,
|
||||||
|
uint32_t seq,
|
||||||
|
const void *data,
|
||||||
|
size_t size,
|
||||||
|
void *user_data)
|
||||||
|
{
|
||||||
|
struct impl *this = user_data;
|
||||||
|
this->transport = NULL;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static void transport_destroy(void *data)
|
static void transport_destroy(void *data)
|
||||||
{
|
{
|
||||||
struct impl *this = data;
|
struct impl *this = data;
|
||||||
spa_log_debug(this->log, "transport %p destroy", this->transport);
|
spa_log_debug(this->log, "transport %p destroy", this->transport);
|
||||||
this->transport = NULL;
|
spa_loop_invoke(this->data_loop, do_transport_destroy, 0, NULL, 0, true, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct spa_bt_transport_events transport_events = {
|
static const struct spa_bt_transport_events transport_events = {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue