[vlc-commits] preparser: fix timeout

Thomas Guillem git at videolan.org
Tue Sep 27 19:11:38 CEST 2016


vlc | branch: master | Thomas Guillem <thomas at gllm.fr> | Tue Sep 27 15:58:53 2016 +0200| [94def8559b5e45cfb58d2d0d477d86a8dab17a98] | committer: Thomas Guillem

preparser: fix timeout

input_Stop() must be called before input_Close() in case of timeout.

closes #17353

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

 src/playlist/preparser.c | 56 ++++++++++++++++++++++++++++++------------------
 1 file changed, 35 insertions(+), 21 deletions(-)

diff --git a/src/playlist/preparser.c b/src/playlist/preparser.c
index 0dc31e5..e4a219c 100644
--- a/src/playlist/preparser.c
+++ b/src/playlist/preparser.c
@@ -52,9 +52,13 @@ struct playlist_preparser_t
     playlist_fetcher_t  *p_fetcher;
     mtime_t              default_timeout;
 
-    input_thread_t      *input;
     void                *input_id;
-    bool                 input_done;
+    enum {
+        INPUT_INIT,
+        INPUT_RUNNING,
+        INPUT_STOPPED,
+        INPUT_CANCELED,
+    } input_state;
 
     vlc_mutex_t     lock;
     vlc_cond_t      wait;
@@ -75,9 +79,8 @@ playlist_preparser_t *playlist_preparser_New( vlc_object_t *parent )
     if( !p_preparser )
         return NULL;
 
-    p_preparser->input = NULL;
     p_preparser->input_id = NULL;
-    p_preparser->input_done = false;
+    p_preparser->input_state = INPUT_INIT;
     p_preparser->object = parent;
     p_preparser->default_timeout = var_InheritInteger( parent, "preparse-timeout" );
     p_preparser->p_fetcher = playlist_fetcher_New( parent );
@@ -149,8 +152,8 @@ void playlist_preparser_Cancel( playlist_preparser_t *p_preparser, void *id )
     /* Stop the input_thread reading the item (if any) */
     if( p_preparser->input_id == id )
     {
-        assert( p_preparser->input != NULL );
-        input_Stop( p_preparser->input );
+        p_preparser->input_state = INPUT_CANCELED;
+        vlc_cond_signal( &p_preparser->thread_wait );
     }
     vlc_mutex_unlock( &p_preparser->lock );
 }
@@ -167,8 +170,8 @@ void playlist_preparser_Delete( playlist_preparser_t *p_preparser )
         REMOVE_ELEM( p_preparser->pp_waiting, p_preparser->i_waiting, 0 );
     }
 
-    if( p_preparser->input != NULL )
-        input_Stop( p_preparser->input );
+    p_preparser->input_state = INPUT_CANCELED;
+    vlc_cond_signal( &p_preparser->thread_wait );
 
     while( p_preparser->b_live )
         vlc_cond_wait( &p_preparser->wait, &p_preparser->lock );
@@ -196,8 +199,15 @@ static int InputEvent( vlc_object_t *obj, const char *varname,
 
     if( event == INPUT_EVENT_DEAD )
     {
-        preparser->input_done = true;
-        vlc_cond_signal( &preparser->thread_wait );
+        vlc_mutex_lock( &preparser->lock );
+
+        if( preparser->input_state != INPUT_INIT )
+        {
+            preparser->input_state = INPUT_STOPPED;
+            vlc_cond_signal( &preparser->thread_wait );
+        }
+
+        vlc_mutex_unlock( &preparser->lock );
     }
 
     (void) obj; (void) varname; (void) old;
@@ -244,26 +254,29 @@ static void Preparse( playlist_preparser_t *preparser,
         {
             vlc_mutex_lock( &preparser->lock );
 
-            preparser->input = input;
-            preparser->input_done = false;
+            preparser->input_state = INPUT_RUNNING;
             preparser->input_id = p_entry->id;
 
             if( p_entry->timeout > 0 )
             {
                 mtime_t deadline = mdate() + p_entry->timeout;
-                int ret = 0;
-                while( !preparser->input_done && ret == 0 )
-                    ret = vlc_cond_timedwait( &preparser->thread_wait,
-                                              &preparser->lock, deadline );
-                status = ret == 0 ? ITEM_PREPARSE_DONE : ITEM_PREPARSE_TIMEOUT;
+                while( preparser->input_state == INPUT_RUNNING )
+                {
+                    if( vlc_cond_timedwait( &preparser->thread_wait,
+                                            &preparser->lock, deadline ) )
+                        preparser->input_state = INPUT_CANCELED; /* timeout */
+                }
             }
             else
             {
-                while( !preparser->input_done )
+                while( preparser->input_state == INPUT_RUNNING )
                     vlc_cond_wait( &preparser->thread_wait, &preparser->lock );
-                status = ITEM_PREPARSE_DONE;
             }
-            preparser->input = NULL;
+            assert( preparser->input_state == INPUT_STOPPED
+                 || preparser->input_state == INPUT_CANCELED );
+            status = preparser->input_state == INPUT_STOPPED ?
+                     ITEM_PREPARSE_DONE : ITEM_PREPARSE_TIMEOUT;
+            preparser->input_state = INPUT_INIT;
             preparser->input_id = NULL;
 
             vlc_mutex_unlock( &preparser->lock );
@@ -272,6 +285,8 @@ static void Preparse( playlist_preparser_t *preparser,
             status = ITEM_PREPARSE_FAILED;
 
         var_DelCallback( input, "intf-event", InputEvent, preparser );
+        if( status == ITEM_PREPARSE_TIMEOUT )
+            input_Stop( input );
         input_Close( input );
 
         var_SetAddress( preparser->object, "item-change", p_item );
@@ -280,7 +295,6 @@ static void Preparse( playlist_preparser_t *preparser,
     }
     else if (!b_preparse)
         input_item_SignalPreparseEnded( p_item, ITEM_PREPARSE_SKIPPED );
-
 }
 
 /**



More information about the vlc-commits mailing list