bluez5: destroy update_delay_event and fd on media-source transport_start failure

Symmetric follow-up to 47a3479490 which fixed
the same leak in media-sink. media-source transport_start() registers
update_delay_event and dups the transport fd before ensuring SCO I/O; on
HFP failure the fail path only deinited codec_data, leaking the event
source and fd. Early allocation failures also returned without cleanup.

Mirror media-sink: destroy update_delay_event, close the dup'd fd, clear
the decode buffer, and route early errors through the same fail path.
This commit is contained in:
zuozhiwei 2026-07-10 17:36:05 +08:00 committed by Wim Taymans
parent 9106065997
commit 4822d2438a

View file

@ -1001,8 +1001,10 @@ static int transport_start(struct impl *this)
&port->current_format, &port->current_format,
this->codec_props, this->codec_props,
this->transport->read_mtu); this->transport->read_mtu);
if (this->codec_data == NULL) if (this->codec_data == NULL) {
return -EIO; res = -EIO;
goto fail;
}
spa_log_info(this->log, "%p: using %s codec %s", this, spa_log_info(this->log, "%p: using %s codec %s", this,
media_codec_kind_str(this->codec), this->codec->description); media_codec_kind_str(this->codec), this->codec->description);
@ -1012,8 +1014,10 @@ static int transport_start(struct impl *this)
* and this won't work properly with epoll. Always dup to avoid problems. * and this won't work properly with epoll. Always dup to avoid problems.
*/ */
this->fd = dup(this->transport->fd); this->fd = dup(this->transport->fd);
if (this->fd < 0) if (this->fd < 0) {
return -errno; res = -errno;
goto fail;
}
val = 6; val = 6;
if (setsockopt(this->fd, SOL_SOCKET, SO_PRIORITY, &val, sizeof(val)) < 0) if (setsockopt(this->fd, SOL_SOCKET, SO_PRIORITY, &val, sizeof(val)) < 0)
@ -1025,7 +1029,7 @@ static int transport_start(struct impl *this)
if ((res = spa_bt_decode_buffer_init(&port->buffer, this->log, if ((res = spa_bt_decode_buffer_init(&port->buffer, this->log,
port->frame_size, port->current_format.info.raw.rate, port->frame_size, port->current_format.info.raw.rate,
this->quantum_limit, this->quantum_limit)) < 0) this->quantum_limit, this->quantum_limit)) < 0)
return res; goto fail;
spa_bt_decode_buffer_set_target_latency(&port->buffer, (int32_t) this->decode_buffer_target); spa_bt_decode_buffer_set_target_latency(&port->buffer, (int32_t) this->decode_buffer_target);
@ -1066,8 +1070,10 @@ static int transport_start(struct impl *this)
spa_strerror(res)); spa_strerror(res));
} else { } else {
spa_zero(this->source); spa_zero(this->source);
if (spa_bt_transport_ensure_sco_io(this->transport, this->data_loop, this->data_system) < 0) if (spa_bt_transport_ensure_sco_io(this->transport, this->data_loop, this->data_system) < 0) {
res = -EIO;
goto fail; goto fail;
}
spa_loop_locked(this->data_loop, do_start_sco_iso_io, 0, NULL, 0, this); spa_loop_locked(this->data_loop, do_start_sco_iso_io, 0, NULL, 0, this);
} }
@ -1079,11 +1085,20 @@ static int transport_start(struct impl *this)
return 0; return 0;
fail: fail:
if (this->update_delay_event) {
spa_loop_utils_destroy_source(this->loop_utils, this->update_delay_event);
this->update_delay_event = NULL;
}
if (this->fd >= 0) {
close(this->fd);
this->fd = -1;
}
spa_bt_decode_buffer_clear(&port->buffer);
if (this->codec_data) { if (this->codec_data) {
this->codec->deinit(this->codec_data); this->codec->deinit(this->codec_data);
this->codec_data = NULL; this->codec_data = NULL;
} }
return -EIO; return res;
} }
static int do_start(struct impl *this) static int do_start(struct impl *this)