[FFmpeg-cvslog] pthread_frame: use a thread-safe way for signalling threads to die

Anton Khirnov git at videolan.org
Wed Mar 22 19:10:24 EET 2017


ffmpeg | branch: master | Anton Khirnov <anton at khirnov.net> | Sun Jul 17 23:30:52 2016 +0200| [db2733256db323e4b88a34b135320f33274148e2] | committer: Anton Khirnov

pthread_frame: use a thread-safe way for signalling threads to die

Current code uses a plain int in a racy way, which is UB.

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

 libavcodec/pthread_frame.c | 20 +++++++++++---------
 1 file changed, 11 insertions(+), 9 deletions(-)

diff --git a/libavcodec/pthread_frame.c b/libavcodec/pthread_frame.c
index c72da53..0549f42 100644
--- a/libavcodec/pthread_frame.c
+++ b/libavcodec/pthread_frame.c
@@ -90,6 +90,8 @@ typedef struct PerThreadContext {
 
     AVFrame *requested_frame;       ///< AVFrame the codec passed to get_buffer()
     int      requested_flags;       ///< flags passed to get_buffer() for requested_frame
+
+    int die;                       ///< Set when the thread should exit.
 } PerThreadContext;
 
 /**
@@ -108,8 +110,6 @@ typedef struct FrameThreadContext {
                                     * Set for the first N packets, where N is the number of threads.
                                     * While it is set, ff_thread_en/decode_frame won't return any results.
                                     */
-
-    int die;                       ///< Set when threads should exit.
 } FrameThreadContext;
 
 /**
@@ -122,20 +122,22 @@ typedef struct FrameThreadContext {
 static attribute_align_arg void *frame_worker_thread(void *arg)
 {
     PerThreadContext *p = arg;
-    FrameThreadContext *fctx = p->parent;
     AVCodecContext *avctx = p->avctx;
     const AVCodec *codec = avctx->codec;
 
     while (1) {
-        if (p->state == STATE_INPUT_READY && !fctx->die) {
+        if (p->state == STATE_INPUT_READY) {
             pthread_mutex_lock(&p->mutex);
-            while (p->state == STATE_INPUT_READY && !fctx->die)
+            while (p->state == STATE_INPUT_READY) {
+                if (p->die) {
+                    pthread_mutex_unlock(&p->mutex);
+                    goto die;
+                }
                 pthread_cond_wait(&p->input_cond, &p->mutex);
+            }
             pthread_mutex_unlock(&p->mutex);
         }
 
-        if (fctx->die) break;
-
         if (!codec->update_thread_context && avctx->thread_safe_callbacks)
             ff_thread_finish_setup(avctx);
 
@@ -161,6 +163,7 @@ static attribute_align_arg void *frame_worker_thread(void *arg)
 
         pthread_mutex_unlock(&p->mutex);
     }
+die:
 
     return NULL;
 }
@@ -504,12 +507,11 @@ void ff_frame_thread_free(AVCodecContext *avctx, int thread_count)
     if (fctx->prev_thread && fctx->prev_thread != fctx->threads)
         update_context_from_thread(fctx->threads->avctx, fctx->prev_thread->avctx, 0);
 
-    fctx->die = 1;
-
     for (i = 0; i < thread_count; i++) {
         PerThreadContext *p = &fctx->threads[i];
 
         pthread_mutex_lock(&p->mutex);
+        p->die = 1;
         pthread_cond_signal(&p->input_cond);
         pthread_mutex_unlock(&p->mutex);
 



More information about the ffmpeg-cvslog mailing list