diff options
author | Nicolas George <nicolas.george@normalesup.org> | 2012-03-15 12:19:37 +0100 |
---|---|---|
committer | Nicolas George <nicolas.george@normalesup.org> | 2012-03-17 14:43:37 +0100 |
commit | 463705bd1c644bbdded7bcf9f619bcb4203d562f (patch) | |
tree | 384ffbf7e8580cfecb34fa9c2e954b90b2c2f3e9 /libavformat | |
parent | d9f26a0d71e3f726cb7a764fa274aa84441a2ddb (diff) | |
download | ffmpeg-463705bd1c644bbdded7bcf9f619bcb4203d562f.tar.gz |
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 'libavformat')
-rw-r--r-- | libavformat/udp.c | 18 |
1 files changed, 10 insertions, 8 deletions
diff --git a/libavformat/udp.c b/libavformat/udp.c index 17bf434759..84edece69d 100644 --- a/libavformat/udp.c +++ b/libavformat/udp.c @@ -336,11 +336,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; @@ -590,7 +585,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) { @@ -614,12 +609,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); } |