Zebediah Figura : winegstreamer: Properly clean up from failure in wg_parser_connect().

Alexandre Julliard julliard at winehq.org
Thu Sep 16 15:34:30 CDT 2021


Module: wine
Branch: master
Commit: 721b1eb2ebe5c3eaab8ac3fb1e4f4648cbee5b4d
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=721b1eb2ebe5c3eaab8ac3fb1e4f4648cbee5b4d

Author: Zebediah Figura <zfigura at codeweavers.com>
Date:   Wed Sep 15 18:00:07 2021 -0500

winegstreamer: Properly clean up from failure in wg_parser_connect().

In particular, unset the sink_connected value, and make sure that subsequent
wg_parser_get_read_request calls don't hang.

Signed-off-by: Zebediah Figura <zfigura at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/winegstreamer/wg_parser.c | 76 +++++++++++++++++++++++++++++-------------
 1 file changed, 53 insertions(+), 23 deletions(-)

diff --git a/dlls/winegstreamer/wg_parser.c b/dlls/winegstreamer/wg_parser.c
index bf5a51aeaf4..119cbffbd88 100644
--- a/dlls/winegstreamer/wg_parser.c
+++ b/dlls/winegstreamer/wg_parser.c
@@ -1034,6 +1034,30 @@ static struct wg_parser_stream *create_stream(struct wg_parser *parser)
     return stream;
 }
 
+static void free_stream(struct wg_parser_stream *stream)
+{
+    if (stream->their_src)
+    {
+        if (stream->post_sink)
+        {
+            gst_pad_unlink(stream->their_src, stream->post_sink);
+            gst_pad_unlink(stream->post_src, stream->my_sink);
+            gst_object_unref(stream->post_src);
+            gst_object_unref(stream->post_sink);
+            stream->post_src = stream->post_sink = NULL;
+        }
+        else
+            gst_pad_unlink(stream->their_src, stream->my_sink);
+        gst_object_unref(stream->their_src);
+    }
+    gst_object_unref(stream->my_sink);
+
+    pthread_cond_destroy(&stream->event_cond);
+    pthread_cond_destroy(&stream->event_empty_cond);
+
+    free(stream);
+}
+
 static void pad_added_cb(GstElement *element, GstPad *pad, gpointer user)
 {
     struct wg_parser *parser = user;
@@ -1520,14 +1544,14 @@ static HRESULT CDECL wg_parser_connect(struct wg_parser *parser, uint64_t file_s
     parser->error = false;
 
     if (!parser->init_gst(parser))
-        return E_FAIL;
+        goto out;
 
     gst_element_set_state(parser->container, GST_STATE_PAUSED);
     ret = gst_element_get_state(parser->container, NULL, NULL, -1);
     if (ret == GST_STATE_CHANGE_FAILURE)
     {
         GST_ERROR("Failed to play stream.\n");
-        return E_FAIL;
+        goto out;
     }
 
     pthread_mutex_lock(&parser->mutex);
@@ -1537,7 +1561,7 @@ static HRESULT CDECL wg_parser_connect(struct wg_parser *parser, uint64_t file_s
     if (parser->error)
     {
         pthread_mutex_unlock(&parser->mutex);
-        return E_FAIL;
+        goto out;
     }
 
     for (i = 0; i < parser->stream_count; ++i)
@@ -1577,7 +1601,7 @@ static HRESULT CDECL wg_parser_connect(struct wg_parser *parser, uint64_t file_s
             if (parser->error)
             {
                 pthread_mutex_unlock(&parser->mutex);
-                return E_FAIL;
+                goto out;
             }
             if (gst_pad_query_duration(stream->their_src, GST_FORMAT_TIME, &duration))
             {
@@ -1614,30 +1638,36 @@ static HRESULT CDECL wg_parser_connect(struct wg_parser *parser, uint64_t file_s
 
     parser->next_offset = 0;
     return S_OK;
-}
 
-static void free_stream(struct wg_parser_stream *stream)
-{
-    if (stream->their_src)
+out:
+    if (parser->container)
+        gst_element_set_state(parser->container, GST_STATE_NULL);
+    if (parser->their_sink)
     {
-        if (stream->post_sink)
-        {
-            gst_pad_unlink(stream->their_src, stream->post_sink);
-            gst_pad_unlink(stream->post_src, stream->my_sink);
-            gst_object_unref(stream->post_src);
-            gst_object_unref(stream->post_sink);
-            stream->post_src = stream->post_sink = NULL;
-        }
-        else
-            gst_pad_unlink(stream->their_src, stream->my_sink);
-        gst_object_unref(stream->their_src);
+        gst_pad_unlink(parser->my_src, parser->their_sink);
+        gst_object_unref(parser->their_sink);
+        parser->my_src = parser->their_sink = NULL;
     }
-    gst_object_unref(stream->my_sink);
 
-    pthread_cond_destroy(&stream->event_cond);
-    pthread_cond_destroy(&stream->event_empty_cond);
+    for (i = 0; i < parser->stream_count; ++i)
+        free_stream(parser->streams[i]);
+    parser->stream_count = 0;
+    free(parser->streams);
+    parser->streams = NULL;
 
-    free(stream);
+    if (parser->container)
+    {
+        gst_element_set_bus(parser->container, NULL);
+        gst_object_unref(parser->container);
+        parser->container = NULL;
+    }
+
+    pthread_mutex_lock(&parser->mutex);
+    parser->sink_connected = false;
+    pthread_mutex_unlock(&parser->mutex);
+    pthread_cond_signal(&parser->read_cond);
+
+    return E_FAIL;
 }
 
 static void CDECL wg_parser_disconnect(struct wg_parser *parser)




More information about the wine-cvs mailing list