]> git.sesse.net Git - mlt/commitdiff
Fix race condition in mlt_consumer_stop().
authorDan Dennedy <dan@dennedy.org>
Sat, 27 Apr 2013 19:17:57 +0000 (12:17 -0700)
committerDan Dennedy <dan@dennedy.org>
Sat, 27 Apr 2013 19:17:57 +0000 (12:17 -0700)
src/framework/mlt_consumer.c
src/modules/sdl/consumer_sdl_preview.c

index 5cd7bc6fa405da45b3a05d9cacebc927517d8a2c..fad0701e63deaa52a0e7f8f34cdf1b3b017edaf8 100644 (file)
@@ -1109,8 +1109,15 @@ static void consumer_work_start( mlt_consumer self )
 static void consumer_read_ahead_stop( mlt_consumer self )
 {
        // Make sure we're running
+// TODO improve support for atomic ops in general (see libavutil/atomic.h)
+#ifdef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4
+       if ( __sync_val_compare_and_swap( &self->started, 1, 0 ) )
+       {
+#else
        if ( self->started )
        {
+               self->started = 0;
+#endif
                // Inform thread to stop
                self->ahead = 0;
 
@@ -1126,7 +1133,6 @@ static void consumer_read_ahead_stop( mlt_consumer self )
 
                // Join the thread
                pthread_join( self->ahead_thread, NULL );
-               self->started = 0;
 
                // Destroy the frame queue mutex
                pthread_mutex_destroy( &self->queue_mutex );
@@ -1152,8 +1158,14 @@ static void consumer_read_ahead_stop( mlt_consumer self )
 static void consumer_work_stop( mlt_consumer self )
 {
        // Make sure we're running
+#ifdef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4
+       if ( __sync_val_compare_and_swap( &self->started, 1, 0 ) )
+       {
+#else
        if ( self->started )
        {
+               self->started = 0;
+#endif
                // Inform thread to stop
                self->ahead = 0;
 
@@ -1181,9 +1193,6 @@ static void consumer_work_stop( mlt_consumer self )
                if ( self->threads )
                        free( self->threads );
 
-               // Indicate that worker threads no longer running
-               self->started = 0;
-
                // Destroy the mutexes
                pthread_mutex_destroy( &self->queue_mutex );
                pthread_mutex_destroy( &self->done_mutex );
@@ -1220,15 +1229,15 @@ void mlt_consumer_purge( mlt_consumer self )
                pthread_cond_broadcast( &self->put_cond );
                pthread_mutex_unlock( &self->put_mutex );
 
-               if ( self->ahead && self->real_time )
+               if ( self->started && self->real_time )
                        pthread_mutex_lock( &self->queue_mutex );
 
                if ( self->purge )
                        self->purge( self );
 
-               while ( self->ahead && mlt_deque_count( self->queue ) )
+               while ( self->started && mlt_deque_count( self->queue ) )
                        mlt_frame_close( mlt_deque_pop_back( self->queue ) );
-               if ( self->ahead && self->real_time )
+               if ( self->started && self->real_time )
                {
                        self->is_purge = 1;
                        pthread_cond_broadcast( &self->queue_cond );
index 9710bdfe12dee8510dd944cef98cc2379c24f8d9..6f33e2c230ec9d5f962b2eac9fa56bdb63e7d10b 100644 (file)
@@ -406,7 +406,8 @@ static void *consumer_thread( void *arg )
                                if ( pause )
                                {
                                        // Start the still consumer
-                                       mlt_consumer_stop( self->play );
+                                       if ( !mlt_consumer_is_stopped( self->play ) )
+                                               mlt_consumer_stop( self->play );
                                        self->last_speed = speed;
                                        self->active = self->still;
                                        self->ignore_change = 0;