On Fri, 20 May 2011, Luca Barbato wrote:
> The connect() timeout can take minutes, gets misreported as EIO and
> isn't interruptible.
> ---
> libavformat/tcp.c | 16 +++++++++++-----
> 1 files changed, 11 insertions(+), 5 deletions(-)
>
> diff --git a/libavformat/tcp.c b/libavformat/tcp.c
> index 0cb3ae3..cdab57c 100644
> --- a/libavformat/tcp.c
> +++ b/libavformat/tcp.c
> @@ -45,6 +45,7 @@ static int tcp_open(URLContext *h, const char *uri, int
> flags)
> char buf[256];
> int ret;
> socklen_t optlen;
> + int timeout = 20;
> char hostname[1024],proto[1024],path[1024];
> char portstr[10];
>
The unit of timeout needs to be specified somewhere. And isn't 20 x 100 ms
a bit low?
> @@ -57,6 +58,9 @@ static int tcp_open(URLContext *h, const char *uri, int
> flags)
> if (p) {
> if (av_find_info_tag(buf, sizeof(buf), "listen", p))
> listen_socket = 1;
> + if (av_find_info_tag(buf, sizeof(buf), "timeout", p)) {
> + timeout = strtol(buf, NULL, 10);
> + }
> }
> memset(&hints, 0, sizeof(hints));
> hints.ai_family = AF_UNSPEC;
> @@ -73,6 +77,7 @@ static int tcp_open(URLContext *h, const char *uri, int
> flags)
> cur_ai = ai;
>
> restart:
> + ret = AVERROR(EIO);
> fd = socket(cur_ai->ai_family, cur_ai->ai_socktype, cur_ai->ai_protocol);
> if (fd < 0)
> goto fail;
> @@ -86,11 +91,10 @@ static int tcp_open(URLContext *h, const char *uri, int
> flags)
> fd = fd1;
> } else {
> redo:
> + ff_socket_nonblock(fd, 1);
> ret = connect(fd, cur_ai->ai_addr, cur_ai->ai_addrlen);
> }
>
> - ff_socket_nonblock(fd, 1);
> -
Doesn't this miss setting listening sockets nonblocking?
> if (ret < 0) {
> struct pollfd p = {fd, POLLOUT, 0};
> if (ff_neterrno() == AVERROR(EINTR)) {
> @@ -105,7 +109,7 @@ static int tcp_open(URLContext *h, const char *uri, int
> flags)
> goto fail;
>
> /* wait until we are connected or until abort */
> - for(;;) {
> + while(timeout--) {
> if (url_interrupt_cb()) {
> ret = AVERROR_EXIT;
> goto fail1;
> @@ -114,7 +118,10 @@ static int tcp_open(URLContext *h, const char *uri, int
> flags)
> if (ret > 0)
> break;
> }
> -
> + if (ret <= 0) {
> + ret = AVERROR(ETIMEDOUT);
> + goto fail;
> + }
> /* test error */
> optlen = sizeof(ret);
> getsockopt (fd, SOL_SOCKET, SO_ERROR, &ret, &optlen);
> @@ -144,7 +151,6 @@ static int tcp_open(URLContext *h, const char *uri, int
> flags)
> closesocket(fd);
> goto restart;
> }
> - ret = AVERROR(EIO);
When this is removed, I think you need to set ret to ff_neterrno() in this
error checking branch:
if (ff_neterrno() != AVERROR(EINPROGRESS) &&
ff_neterrno() != AVERROR(EAGAIN))
goto fail;
Before that, ret only is the return value from connect or bind.
// Martin
_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel