[vlc-commits] test: player: fix ABA problem

Thomas Guillem git at videolan.org
Wed Nov 28 16:45:44 CET 2018


vlc | branch: master | Thomas Guillem <thomas at gllm.fr> | Wed Nov 28 15:53:43 2018 +0100| [e548bfb9797cb3b0a0a83b07fcad78933c3f84ac] | committer: Thomas Guillem

test: player: fix ABA problem

Don't wait for the last state, but for all forthcoming states. This fixes a
deadlock when the test was waiting for the STARTED event but the playback was
already terminated (so the last event was back to STOPPED).

A=STOPPED
B=STARTED (then PLAYING, STOPPING)
A=STOPPED

> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=e548bfb9797cb3b0a0a83b07fcad78933c3f84ac
---

 test/src/input/player.c | 38 +++++++++++++++++++++++++++++---------
 1 file changed, 29 insertions(+), 9 deletions(-)

diff --git a/test/src/input/player.c b/test/src/input/player.c
index 756ca500db..af3cf55d2b 100644
--- a/test/src/input/player.c
+++ b/test/src/input/player.c
@@ -171,6 +171,8 @@ struct ctx
     struct media_params params;
     float rate;
 
+    size_t last_state_idx;
+
     vlc_cond_t wait;
     struct reports report;
 };
@@ -479,11 +481,24 @@ player_on_media_subitems_changed(vlc_player_t *player, input_item_t *media,
     assert(fabs((report)->pos - (report)->time / (float) ctx->params.length) < 0.001); \
 } while (0)
 
-#define wait_state(ctx, state) do { \
-    vec_on_state_changed *vec = &ctx->report.on_state_changed; \
-    while (vec->size == 0 || VEC_LAST(vec) != state) \
-        vlc_player_CondWait(player, &ctx->wait); \
-} while(0)
+/* Wait for the next state event */
+static inline void
+wait_state(struct ctx *ctx, enum vlc_player_state state)
+{
+    vec_on_state_changed *vec = &ctx->report.on_state_changed;
+    for (;;)
+    {
+        while (vec->size <= ctx->last_state_idx)
+            vlc_player_CondWait(ctx->player, &ctx->wait);
+        for (size_t i = ctx->last_state_idx; i < vec->size; ++i)
+            if ((vec)->data[i] == state)
+            {
+                ctx->last_state_idx = i + 1;
+                return;
+            }
+        ctx->last_state_idx = vec->size;
+    }
+}
 
 #define assert_state(ctx, state) do { \
     vec_on_state_changed *vec = &ctx->report.on_state_changed; \
@@ -586,6 +601,8 @@ REPORT_LIST
     ctx->extra_start_count = 0;
     ctx->program_switch_count = 1;
     ctx->rate = 1.f;
+
+    ctx->last_state_idx = 0;
 };
 
 static input_item_t *
@@ -899,9 +916,14 @@ test_end(struct ctx *ctx)
 {
     vlc_player_t *player = ctx->player;
 
+    /* Don't wait if we already stopped or waited for a stop */
+    const bool wait_stopped =
+        VEC_LAST(&ctx->report.on_state_changed) != VLC_PLAYER_STATE_STOPPED;
+    /* Can be no-op */
     vlc_player_Stop(player);
     assert(vlc_player_GetCurrentMedia(player) != NULL);
-    wait_state(ctx, VLC_PLAYER_STATE_STOPPED);
+    if (wait_stopped)
+        wait_state(ctx, VLC_PLAYER_STATE_STOPPED);
 
     if (!ctx->params.error)
     {
@@ -1342,8 +1364,7 @@ test_unknown_uri(struct ctx *ctx)
     bool success = vlc_vector_push(&ctx->played_medias, media);
     assert(success);
 
-    ret = vlc_player_Start(player);
-    assert(ret == VLC_SUCCESS);
+    player_start(ctx);
 
     wait_state(ctx, VLC_PLAYER_STATE_STARTED);
     wait_state(ctx, VLC_PLAYER_STATE_STOPPED);
@@ -1544,7 +1565,6 @@ test_next_media(struct ctx *ctx)
     const char *media_names[] = { "media1", "media2", "media3" };
     const size_t media_count = ARRAY_SIZE(media_names);
 
-    vlc_player_t *player = ctx->player;
     struct media_params params = DEFAULT_MEDIA_PARAMS(VLC_TICK_FROM_MS(100));
 
     for (size_t i = 0; i < media_count; ++i)



More information about the vlc-commits mailing list