diff options
author | Nicolas George <nicolas.george@normalesup.org> | 2012-03-15 12:19:37 +0100 |
---|---|---|
committer | Joakim Plate <elupus@ecce.se> | 2013-04-06 12:59:47 +0200 |
commit | 3c1ac65278a1a2ba6c6ecc65da21ef8f37a72bf8 (patch) | |
tree | d7fc7b85d5377e3f9441b232ebf8748c510e49c1 /lib/ffmpeg | |
parent | 11220a8b02741e8cdd8ba6ab56bc3e474014e680 (diff) |
udp: fix non-blocking and interrupt handling.
In non-blocking mode, lowest-level read protocols are
supposed block only for a short amount of time to let
retry_transfer_wrapper() check for interrupts.
Also, checking the interrupt_callback in the receiving thread is
wrong, as interrupt_callback is not guaranteed to be thread-safe
and the job is already done by retry_transfer_wrapper(). The error
code was also incorrect.
Bug reported by Andrey Utkin.
Diffstat (limited to 'lib/ffmpeg')
-rw-r--r-- | lib/ffmpeg/libavformat/udp.c | 18 |
1 files changed, 10 insertions, 8 deletions
diff --git a/lib/ffmpeg/libavformat/udp.c b/lib/ffmpeg/libavformat/udp.c index 309b18c4eb..ed1559d1c0 100644 --- a/lib/ffmpeg/libavformat/udp.c +++ b/lib/ffmpeg/libavformat/udp.c @@ -334,11 +334,6 @@ static void *circular_buffer_task( void *_URLContext) int ret; int len; - if (ff_check_interrupt(&h->interrupt_callback)) { - s->circular_buffer_error = AVERROR(EINTR); - goto end; - } - FD_ZERO(&rfds); FD_SET(s->udp_fd, &rfds); tv.tv_sec = 1; @@ -568,7 +563,7 @@ static int udp_read(URLContext *h, uint8_t *buf, int size) { UDPContext *s = h->priv_data; int ret; - int avail; + int avail, nonblock = h->flags & AVIO_FLAG_NONBLOCK; #if HAVE_PTHREADS if (s->fifo) { @@ -592,12 +587,19 @@ static int udp_read(URLContext *h, uint8_t *buf, int size) } else if(s->circular_buffer_error){ pthread_mutex_unlock(&s->mutex); return s->circular_buffer_error; - } else if(h->flags & AVIO_FLAG_NONBLOCK) { + } else if(nonblock) { pthread_mutex_unlock(&s->mutex); return AVERROR(EAGAIN); } else { - pthread_cond_wait(&s->cond, &s->mutex); + /* FIXME: using the monotonic clock would be better, + but it does not exist on all supported platforms. */ + int64_t t = av_gettime() + 100000; + struct timespec tv = { .tv_sec = t / 1000000, + .tv_nsec = (t % 1000000) * 1000 }; + if (pthread_cond_timedwait(&s->cond, &s->mutex, &tv) < 0) + return AVERROR(errno == ETIMEDOUT ? EAGAIN : errno); + nonblock = 1; } } while( 1); } |