From: Giovanni Mascellani <gmascellani(a)codeweavers.com> It is possible that a stream is destroyed while another thread is waiting on event_empty_cond or event_cond. The waiting thread should have the opportunity to be rescheduled and exit the critical section before the condition variables and the mutex are destroyed. --- dlls/winegstreamer/wg_parser.c | 31 ++++++++++++++++++++++++++++--- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/dlls/winegstreamer/wg_parser.c b/dlls/winegstreamer/wg_parser.c index 0573c99858b..feead069391 100644 --- a/dlls/winegstreamer/wg_parser.c +++ b/dlls/winegstreamer/wg_parser.c @@ -102,13 +102,15 @@ struct wg_parser_stream GstSegment segment; struct wg_format preferred_format, current_format; - pthread_cond_t event_cond, event_empty_cond; + pthread_cond_t event_cond, event_empty_cond, free_cond; GstBuffer *buffer; GstMapInfo map_info; - bool flushing, eos, enabled, has_caps; + bool flushing, eos, enabled, has_caps, freeing; uint64_t duration; + + unsigned int waiters; }; static NTSTATUS wg_parser_get_stream_count(void *args) @@ -270,8 +272,15 @@ static NTSTATUS wg_parser_stream_get_buffer(void *args) pthread_mutex_lock(&parser->mutex); - while (!stream->eos && !stream->buffer) + while (!stream->eos && !stream->buffer && !stream->freeing) + { + stream->waiters++; pthread_cond_wait(&stream->event_cond, &parser->mutex); + stream->waiters--; + } + + if (stream->freeing && stream->waiters == 0) + pthread_cond_signal(&stream->free_cond); /* Note that we can both have a buffer and stream->eos, in which case we * must return the buffer. */ @@ -547,7 +556,14 @@ static GstFlowReturn sink_chain_cb(GstPad *pad, GstObject *parent, GstBuffer *bu * implementing a queue object here. */ while (stream->enabled && !stream->flushing && stream->buffer) + { + stream->waiters++; pthread_cond_wait(&stream->event_empty_cond, &parser->mutex); + stream->waiters--; + } + + if (stream->freeing && stream->waiters == 0) + pthread_cond_signal(&stream->free_cond); if (!stream->enabled) { @@ -694,6 +710,7 @@ static struct wg_parser_stream *create_stream(struct wg_parser *parser) stream->current_format.major_type = WG_MAJOR_TYPE_UNKNOWN; pthread_cond_init(&stream->event_cond, NULL); pthread_cond_init(&stream->event_empty_cond, NULL); + pthread_cond_init(&stream->free_cond, NULL); sprintf(pad_name, "qz_sink_%u", parser->stream_count); stream->my_sink = gst_pad_new(pad_name, GST_PAD_SINK); @@ -708,6 +725,13 @@ static struct wg_parser_stream *create_stream(struct wg_parser *parser) static void free_stream(struct wg_parser_stream *stream) { + pthread_mutex_lock(&stream->parser->mutex); + stream->freeing = true; + pthread_cond_signal(&stream->event_cond); + while (stream->waiters != 0) + pthread_cond_wait(&stream->free_cond, &stream->parser->mutex); + pthread_mutex_unlock(&stream->parser->mutex); + if (stream->their_src) { if (stream->post_sink) @@ -722,6 +746,7 @@ static void free_stream(struct wg_parser_stream *stream) pthread_cond_destroy(&stream->event_cond); pthread_cond_destroy(&stream->event_empty_cond); + pthread_cond_destroy(&stream->free_cond); free(stream); } -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/1278