Ticket #1026 (closed defect: fixed)
libavformat::av_read_frame does not return waiting for udp packets when interrupted
| Reported by: | asif | Owned by: | |
|---|---|---|---|
| Priority: | important | Component: | avformat |
| Version: | 0.10 | Keywords: | deadlock,interrupt |
| Cc: | Blocked By: | ||
| Blocking: | Reproduced by developer: | no | |
| Analyzed by developer: | no |
Description
Steps to reproduce:
- Start receiving udp stream.
- Stop the incoming udp stream transmitter.
- udp.c::udp_read will wait for udp.c::circular_buffer_task at pthread_cond_wait(&s->cond, &s->mutex);
- Interrupt udp.c::circular_buffer_task by returning 1 from interrupt_callback. Circular buffer will exit and signal udp_read as well. But the return value is EINTR
- udp.c::udp_read will return to avio.c::retry_transfer_wrapper. This function is ignoring the error and will call udp_read again.
Change History
comment:2 Changed 13 months ago by reimar
The full commit message suggests that a more reasonable solution would be to only allow interrupting read-only URLs:
commit aa612fbb99f6246913a789afde5a26f70c5a9159
Author: Baptiste Coudurier <baptiste.coudurier@gmail.com>
Date: Fri Mar 4 23:43:02 2011 +0100
In retry_transfer_wrapper, do not check url_interrupt_cb, causes problems
when writing and pressing q during encoding. Instead, check url_interrupt_cb
at the end.
Note that when a protocol is interrupted by url_interrupt_cb, some data may
be silently discarded: the protocol context is not suitable for anything
anymore.
Note: See
TracTickets for help on using
tickets.



Possible fix:
author Baptiste Coudurier <baptiste.coudurier@gmail.com> Fri, 4 Mar 2011 04:33:44 +0100 (19:33 -0800) committer Baptiste Coudurier <baptiste.coudurier@gmail.com> Fri, 4 Mar 2011 04:34:59 +0100 (19:34 -0800) File: libavformat/avio.c diff --git a/libavformat/avio.c b/libavformat/avio.c index a19ec37..cf07c6d 100644 (file) --- a/libavformat/avio.c +++ b/libavformat/avio.c @@ -214,8 +214,6 @@ static inline int retry_transfer_wrapper(URLContext *h, unsigned char *buf, int len = 0; while (len < size_min) { - if (url_interrupt_cb()) - return AVERROR(EINTR); ret = transfer_func(h, buf+len, size-len); if (ret == AVERROR(EINTR)) continue;len = 0; while (len < size_min) { ret = transfer_func(h, buf+len, size-len); if (ret == AVERROR(EINTR)) - continue; + return AVERROR(EINTR);