Package: xmms Version: 1.2.10-2 Followup-For: Bug #211842 The problem is that xmms opens an async. socket to the server. It doesn't wait for a response if the particular socket works or not. For example, if a server has AAAA and A address, and first lookup yields AAAA, xmms will send SYN to server but doesn't wait for connection to be established. Well, it does, but too late to go though other addresses. This will cause all sorts of problems if you have multiple, not just AAAA, addresses. If the first one fails, xmms will not go to the next address on the list.
I've attached a patch that will fix the problem. Please apply. The code will need be to be cleaned up a bit (I'll try to do that later on sometime). The IPV4 code is not needed and the #ifdef IPV6 are not needed either because there is *nothing* IPV6 specific in the connection code. - Adam -- System Information: Debian Release: 3.1 APT prefers unstable APT policy: (500, 'unstable'), (1, 'experimental') Architecture: i386 (i686) Kernel: Linux 2.6.10-1-k7 Locale: LANG=C, LC_CTYPE=C (charmap=ANSI_X3.4-1968) Versions of packages xmms depends on: ii libc6 2.3.2.ds1-20 GNU C Library: Shared libraries an ii libglib1.2 1.2.10-9 The GLib library of C routines ii libgtk1.2 1.2.10-17 The GIMP Toolkit set of widgets fo ii libice6 4.3.0.dfsg.1-12 Inter-Client Exchange library ii libsm6 4.3.0.dfsg.1-12 X Window System Session Management ii libx11-6 4.3.0.dfsg.1-12 X Window System protocol client li ii libxext6 4.3.0.dfsg.1-12 X Window System miscellaneous exte ii libxi6 4.3.0.dfsg.1-12 X Window System Input extension li ii xlibs 4.3.0.dfsg.1-12 X Keyboard Extension (XKB) configu -- no debconf information
--- xmms-1.2.10/Input/mpg123/http.c 2003-12-07 11:09:49.000000000 -0600 +++ xmms-1.2.10/Input/mpg123/http.c 2005-02-24 12:17:14.278071456 -0600 @@ -364,6 +364,7 @@ g_snprintf(service, 6, "%d", cport); memset(&hints, 0, sizeof(hints)); hints.ai_socktype = SOCK_STREAM; + hints.ai_family = PF_UNSPEC; if (! getaddrinfo(chost, service, &hints, &res0)) { eof = TRUE; for (res = res0; res; res = res->ai_next) { @@ -375,10 +376,35 @@ g_free(status); ((struct sockaddr_in6 *)res->ai_addr)->sin6_port = htons(cport); if (connect(sock, res->ai_addr, res->ai_addrlen) < 0) { + int connected = 0; + if (errno != EINPROGRESS) { close(sock); continue; } + /* We are EINPROGRESS. We need to wait if we can actually connect before we can actually + * say that we have a connection as multiple addresses are possible for a host and and + * we should not fail to connect if one address fails. + */ + while (going) { + fd_set set; + FD_ZERO(&set); + FD_SET(sock, &set); + + tv.tv_sec = 0; + tv.tv_usec = 10000; + if (select(sock + 1, NULL, &set, NULL, &tv) > 0) { + err_len = sizeof (error); + getsockopt(sock, SOL_SOCKET, SO_ERROR, &error, &err_len); + if (error == 0) + connected = 1; + break; + } + else if( errno == EBADF || error == ENOMEM ) + break; /* Select failures - break to avoid possible infinite loop */ + } + if( !connected ) + continue; } eof = FALSE; break; --- xmms-1.2.10/Input/vorbis/http.c 2003-09-04 15:59:05.000000000 -0500 +++ xmms-1.2.10/Input/vorbis/http.c 2005-02-24 12:20:22.571446512 -0600 @@ -319,6 +319,7 @@ g_snprintf(service, 6, "%d", cport); memset(&hints, 0, sizeof(hints)); hints.ai_socktype = SOCK_STREAM; + hints.ai_family = PF_UNSPEC; if (! getaddrinfo(chost, service, &hints, &res0)) { eof = TRUE; for (res = res0; res; res = res->ai_next) { @@ -330,10 +331,35 @@ g_free(status); ((struct sockaddr_in6 *)res->ai_addr)->sin6_port = htons(cport); if (connect(sock, res->ai_addr, res->ai_addrlen) < 0) { + int connected = 0; + if (errno != EINPROGRESS) { close(sock); continue; } + /* We are EINPROGRESS. We need to wait if we can actually connect before we can actually + * say that we have a connection as multiple addresses are possible for a host and and + * we should not fail to connect if one address fails. + */ + while (going) { + fd_set set; + FD_ZERO(&set); + FD_SET(sock, &set); + + tv.tv_sec = 0; + tv.tv_usec = 10000; + if (select(sock + 1, NULL, &set, NULL, &tv) > 0) { + err_len = sizeof (error); + getsockopt(sock, SOL_SOCKET, SO_ERROR, &error, &err_len); + if (error == 0) + connected = 1; + break; + } + else if( errno == EBADF || error == ENOMEM ) + break; /* Select failures - break to avoid possible infinite loop */ + } + if( !connected ) + continue; } eof = FALSE; break;