mirror of
				https://gitlab.freedesktop.org/pipewire/pipewire.git
				synced 2025-11-03 09:01:54 -05:00 
			
		
		
		
	stream: don't allow _connect twice
Check if we already are connected and return -EBUSY to avoid crashing. Fixes #3091
This commit is contained in:
		
							parent
							
								
									fa3ee2e20b
								
							
						
					
					
						commit
						60718c4b4f
					
				
					 2 changed files with 43 additions and 10 deletions
				
			
		| 
						 | 
				
			
			@ -144,7 +144,6 @@ struct filter {
 | 
			
		|||
 | 
			
		||||
	unsigned int disconnecting:1;
 | 
			
		||||
	unsigned int disconnect_core:1;
 | 
			
		||||
	unsigned int subscribe:1;
 | 
			
		||||
	unsigned int draining:1;
 | 
			
		||||
	unsigned int allow_mlock:1;
 | 
			
		||||
	unsigned int warn_mlock:1;
 | 
			
		||||
| 
						 | 
				
			
			@ -1497,6 +1496,9 @@ pw_filter_connect(struct pw_filter *filter,
 | 
			
		|||
	uint32_t i;
 | 
			
		||||
	struct spa_dict_item items[1];
 | 
			
		||||
 | 
			
		||||
	if (filter->proxy != NULL || filter->state != PW_FILTER_STATE_UNCONNECTED)
 | 
			
		||||
		return -EBUSY;
 | 
			
		||||
 | 
			
		||||
	pw_log_debug("%p: connect", filter);
 | 
			
		||||
	impl->flags = flags;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1532,6 +1534,8 @@ pw_filter_connect(struct pw_filter *filter,
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
	impl->disconnecting = false;
 | 
			
		||||
	impl->draining = false;
 | 
			
		||||
	impl->driving = false;
 | 
			
		||||
	filter_set_state(filter, PW_FILTER_STATE_CONNECTING, NULL);
 | 
			
		||||
 | 
			
		||||
	if (flags & PW_FILTER_FLAG_DRIVER)
 | 
			
		||||
| 
						 | 
				
			
			@ -1587,6 +1591,10 @@ int pw_filter_disconnect(struct pw_filter *filter)
 | 
			
		|||
	struct filter *impl = SPA_CONTAINER_OF(filter, struct filter, this);
 | 
			
		||||
 | 
			
		||||
	pw_log_debug("%p: disconnect", filter);
 | 
			
		||||
 | 
			
		||||
	if (impl->disconnecting)
 | 
			
		||||
		return -EBUSY;
 | 
			
		||||
 | 
			
		||||
	impl->disconnecting = true;
 | 
			
		||||
 | 
			
		||||
	if (filter->proxy) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1332,6 +1332,14 @@ static int node_event_param(void *object, int seq,
 | 
			
		|||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void node_event_destroy(void *data)
 | 
			
		||||
{
 | 
			
		||||
	struct pw_stream *stream = data;
 | 
			
		||||
	struct stream *impl = SPA_CONTAINER_OF(stream, struct stream, this);
 | 
			
		||||
	spa_hook_remove(&stream->node_listener);
 | 
			
		||||
	impl->node = NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void node_event_info(void *data, const struct pw_node_info *info)
 | 
			
		||||
{
 | 
			
		||||
	struct pw_stream *stream = data;
 | 
			
		||||
| 
						 | 
				
			
			@ -1359,6 +1367,7 @@ static void node_event_info(void *data, const struct pw_node_info *info)
 | 
			
		|||
 | 
			
		||||
static const struct pw_impl_node_events node_events = {
 | 
			
		||||
	PW_VERSION_IMPL_NODE_EVENTS,
 | 
			
		||||
	.destroy = node_event_destroy,
 | 
			
		||||
	.info_changed = node_event_info,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1786,8 +1795,7 @@ static const char *get_media_class(struct stream *impl)
 | 
			
		|||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
SPA_EXPORT
 | 
			
		||||
int
 | 
			
		||||
SPA_EXPORT int
 | 
			
		||||
pw_stream_connect(struct pw_stream *stream,
 | 
			
		||||
		  enum pw_direction direction,
 | 
			
		||||
		  uint32_t target_id,
 | 
			
		||||
| 
						 | 
				
			
			@ -1803,6 +1811,10 @@ pw_stream_connect(struct pw_stream *stream,
 | 
			
		|||
	int res;
 | 
			
		||||
 | 
			
		||||
	pw_log_debug("%p: connect target:%d", stream, target_id);
 | 
			
		||||
 | 
			
		||||
	if (impl->node != NULL || stream->state != PW_STREAM_STATE_UNCONNECTED)
 | 
			
		||||
		return -EBUSY;
 | 
			
		||||
 | 
			
		||||
	impl->direction =
 | 
			
		||||
	    direction == PW_DIRECTION_INPUT ? SPA_DIRECTION_INPUT : SPA_DIRECTION_OUTPUT;
 | 
			
		||||
	impl->flags = flags;
 | 
			
		||||
| 
						 | 
				
			
			@ -1879,6 +1891,11 @@ pw_stream_connect(struct pw_stream *stream,
 | 
			
		|||
		return res;
 | 
			
		||||
 | 
			
		||||
	impl->disconnecting = false;
 | 
			
		||||
	impl->drained = false;
 | 
			
		||||
	impl->draining = false;
 | 
			
		||||
	impl->driving = false;
 | 
			
		||||
	impl->trigger = false;
 | 
			
		||||
	impl->using_trigger = false;
 | 
			
		||||
	stream_set_state(stream, PW_STREAM_STATE_CONNECTING, NULL);
 | 
			
		||||
 | 
			
		||||
	if ((str = getenv("PIPEWIRE_NODE")) != NULL)
 | 
			
		||||
| 
						 | 
				
			
			@ -2026,7 +2043,7 @@ int pw_stream_disconnect(struct pw_stream *stream)
 | 
			
		|||
	pw_log_debug("%p: disconnect", stream);
 | 
			
		||||
 | 
			
		||||
	if (impl->disconnecting)
 | 
			
		||||
		return 0;
 | 
			
		||||
		return -EBUSY;
 | 
			
		||||
 | 
			
		||||
	impl->disconnecting = true;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -2038,10 +2055,9 @@ int pw_stream_disconnect(struct pw_stream *stream)
 | 
			
		|||
		stream->proxy = NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (impl->node) {
 | 
			
		||||
	if (impl->node)
 | 
			
		||||
		pw_impl_node_destroy(impl->node);
 | 
			
		||||
		impl->node = NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (impl->disconnect_core) {
 | 
			
		||||
		impl->disconnect_core = false;
 | 
			
		||||
		spa_hook_remove(&stream->core_listener);
 | 
			
		||||
| 
						 | 
				
			
			@ -2172,9 +2188,13 @@ SPA_EXPORT
 | 
			
		|||
int pw_stream_set_active(struct pw_stream *stream, bool active)
 | 
			
		||||
{
 | 
			
		||||
	struct stream *impl = SPA_CONTAINER_OF(stream, struct stream, this);
 | 
			
		||||
 | 
			
		||||
	pw_log_debug("%p: active:%d", stream, active);
 | 
			
		||||
	if (impl->node)
 | 
			
		||||
		pw_impl_node_set_active(impl->node, active);
 | 
			
		||||
 | 
			
		||||
	if (impl->node == NULL)
 | 
			
		||||
		return -EIO;
 | 
			
		||||
 | 
			
		||||
	pw_impl_node_set_active(impl->node, active);
 | 
			
		||||
 | 
			
		||||
	if (!active || impl->drained)
 | 
			
		||||
		impl->drained = impl->draining = false;
 | 
			
		||||
| 
						 | 
				
			
			@ -2329,9 +2349,14 @@ SPA_EXPORT
 | 
			
		|||
int pw_stream_flush(struct pw_stream *stream, bool drain)
 | 
			
		||||
{
 | 
			
		||||
	struct stream *impl = SPA_CONTAINER_OF(stream, struct stream, this);
 | 
			
		||||
 | 
			
		||||
	if (impl->node == NULL)
 | 
			
		||||
		return -EIO;
 | 
			
		||||
 | 
			
		||||
	pw_loop_invoke(impl->context->data_loop,
 | 
			
		||||
			drain ? do_drain : do_flush, 1, NULL, 0, true, impl);
 | 
			
		||||
	if (!drain && impl->node != NULL)
 | 
			
		||||
 | 
			
		||||
	if (!drain)
 | 
			
		||||
		spa_node_send_command(impl->node->node,
 | 
			
		||||
				&SPA_NODE_COMMAND_INIT(SPA_NODE_COMMAND_Flush));
 | 
			
		||||
	return 0;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue