summaryrefslogtreecommitdiff
path: root/libavformat/udp.c
diff options
context:
space:
mode:
authorNicolas George <nicolas.george@normalesup.org>2012-03-15 12:19:37 +0100
committerNicolas George <nicolas.george@normalesup.org>2012-03-17 14:43:37 +0100
commit463705bd1c644bbdded7bcf9f619bcb4203d562f (patch)
tree384ffbf7e8580cfecb34fa9c2e954b90b2c2f3e9 /libavformat/udp.c
parentd9f26a0d71e3f726cb7a764fa274aa84441a2ddb (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 'libavformat/udp.c')
-rw-r--r--libavformat/udp.c18
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);
}