[FFmpeg-cvslog] udp: fix segfault on closing

Laurent BRULET git at videolan.org
Sat Jan 14 17:21:56 CET 2012


ffmpeg | branch: master | Laurent BRULET <lbrulet at gmail.com> | Sat Jan 14 17:14:18 2012 +0100| [45c39e566fe6d263e6ce0268b4629e5de3aa4d0c] | committer: Michael Niedermayer

udp: fix segfault on closing

Fixes ticket915

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

 libavformat/udp.c |   38 +++++++++++++++++++++++++++++++++-----
 1 files changed, 33 insertions(+), 5 deletions(-)

diff --git a/libavformat/udp.c b/libavformat/udp.c
index cdcd136..9694ad2 100644
--- a/libavformat/udp.c
+++ b/libavformat/udp.c
@@ -71,6 +71,8 @@ typedef struct {
     pthread_t circular_buffer_thread;
     pthread_mutex_t mutex;
     pthread_cond_t cond;
+    int thread_started;
+    volatile int exit_thread;
 #endif
     uint8_t tmp[UDP_MAX_PKT_SIZE+4];
     int remaining_in_dg;
@@ -327,7 +329,7 @@ static void *circular_buffer_task( void *_URLContext)
     fd_set rfds;
     struct timeval tv;
 
-    for(;;) {
+    while(!s->exit_thread) {
         int left;
         int ret;
         int len;
@@ -525,18 +527,36 @@ static int udp_open(URLContext *h, const char *uri, int flags)
 
 #if HAVE_PTHREADS
     if (!is_output && s->circular_buffer_size) {
+        int ret;
+
         /* start the task going */
         s->fifo = av_fifo_alloc(s->circular_buffer_size);
-        pthread_mutex_init(&s->mutex, NULL);
-        pthread_cond_init(&s->cond, NULL);
-        if (pthread_create(&s->circular_buffer_thread, NULL, circular_buffer_task, h)) {
-            av_log(h, AV_LOG_ERROR, "pthread_create failed\n");
+        ret = pthread_mutex_init(&s->mutex, NULL);
+        if (ret != 0) {
+            av_log(h, AV_LOG_ERROR, "pthread_mutex_init failed : %s\n", strerror(ret));
             goto fail;
         }
+        ret = pthread_cond_init(&s->cond, NULL);
+        if (ret != 0) {
+            av_log(h, AV_LOG_ERROR, "pthread_cond_init failed : %s\n", strerror(ret));
+            goto cond_fail;
+        }
+        ret = pthread_create(&s->circular_buffer_thread, NULL, circular_buffer_task, h);
+        if (ret != 0) {
+            av_log(h, AV_LOG_ERROR, "pthread_create failed : %s\n", strerror(ret));
+            goto thread_fail;
+        }
+        s->thread_started = 1;
     }
 #endif
 
     return 0;
+#if HAVE_PTHREADS
+ thread_fail:
+    pthread_cond_destroy(&s->cond);
+ cond_fail:
+    pthread_mutex_destroy(&s->mutex);
+#endif
  fail:
     if (udp_fd >= 0)
         closesocket(udp_fd);
@@ -617,12 +637,20 @@ static int udp_write(URLContext *h, const uint8_t *buf, int size)
 static int udp_close(URLContext *h)
 {
     UDPContext *s = h->priv_data;
+    int ret;
 
     if (s->is_multicast && (h->flags & AVIO_FLAG_READ))
         udp_leave_multicast_group(s->udp_fd, (struct sockaddr *)&s->dest_addr);
     closesocket(s->udp_fd);
     av_fifo_free(s->fifo);
 #if HAVE_PTHREADS
+    if (s->thread_started) {
+        s->exit_thread = 1;
+        ret = pthread_join(s->circular_buffer_thread, NULL);
+        if (ret != 0)
+            av_log(h, AV_LOG_ERROR, "pthread_join(): %s\n", strerror(ret));
+    }
+
     pthread_mutex_destroy(&s->mutex);
     pthread_cond_destroy(&s->cond);
 #endif



More information about the ffmpeg-cvslog mailing list