Skip to contentSkip to conversation

Fix bogus avdtp error codes management

PATCH In review Fabien Chevalier 3 participants 6 messages Sep 17, 2007 – Sep 18, 2007 Bluetooth drivers

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 Fix bogus avdtp error codes management

Hi Johan & Marcel,

While trying to fix this cross case issue, i came with an issue with the way error codes are handled in avdtp.c.
The issue is basically that the part of the code that retrieves the exact error value is never executed due to premature return.

Please have a look at the current patch.

Fabien

avdtp.c 17 Sep 2007 17:33:24 -0000 renamed from avdtp.c 2 Sep 2007 16:52:50 -0000 1.49 +5 -5
diff -u -1 -0 -r1.49 avdtp.c
@@ -1501,38 +1501,38 @@
        if (cond & G_IO_NVAL)
                return FALSE;
 
        if (!g_slist_find(sessions, session)) {
                debug("l2cap_connect_cb: session got removed");
                return FALSE;
        }
 
        sk = g_io_channel_unix_get_fd(chan);
 
-       if (cond & (G_IO_ERR | G_IO_HUP)) {
-               err = EIO;
-               goto failed;
-       }
-
        len = sizeof(ret);
        if (getsockopt(sk, SOL_SOCKET, SO_ERROR, &ret, &len) < 0) {
                err = errno;
                error("getsockopt(SO_ERROR): %s (%d)", strerror(err), err);
                goto failed;
        }
 
        if (ret != 0) {
                err = ret;
                error("connect(): %s (%d)", strerror(err), err);
                goto failed;
        }
 
+       if (cond & G_IO_HUP) {
+               err = EIO;
+               goto failed;
+       }
+
        ba2str(&session->dst, address);
        debug("AVDTP: connected %s channel to %s",
                        session->pending_open ? "transport" : "signaling",
                        address);
 
        memset(&l2o, 0, sizeof(l2o));
        len = sizeof(l2o);
        if (getsockopt(sk, SOL_L2CAP, L2CAP_OPTIONS, &l2o,
                                &len) < 0) {
                err = errno;

f

begin:vcard
fn:Fabien CHEVALIER
n:CHEVALIER;Fabien
org:SILICOM
adr:;;4 rue de Jouanet; RENNES ATALANTE;;35700;FRANCE email;internet:[email protected] title:Software & Studies Engineer tel;work:+33 (0) 2 99 84 17 17
version:2.1
end:vcard

#1 lore raw

Hi Fabien,

Quoted 6 lines · Fabien Chevalier

While trying to fix this cross case issue, i came with an issue with the way error codes are handled
in avdtp.c.
The issue is basically that the part of the code that retrieves the exact error value is never executed
due to premature return.

Looks fine to me if it works. However, I'd like to hear some comment from Marcel as well. At least my connect(2) manpage implies that a non-blocking connect should always produce a POLLOUT on connection completion regardless if the result was failure or success. So it seems bluez may be behaving differently than other socket types in this respect.

We had a similar issue with the EAGAIN/EINPROGRESS mixup with non-blocking connect's so maybe this issue should also be fixed on the kernel side (however a userspace work-around such as your patch is probably also desirable).

Johan

maintainer
#2 lore raw

Hi Johan,

Quoted 7 lines
Quoted 6 lines

While trying to fix this cross case issue, i came with an issue with the way error codes are handled
in avdtp.c.
The issue is basically that the part of the code that retrieves the exact error value is never executed
due to premature return.

Quoted 6 lines

Looks fine to me if it works. However, I'd like to hear some comment from Marcel as well. At least my connect(2) manpage implies that a non-blocking connect should always produce a POLLOUT on connection completion regardless if the result was failure or success. So it seems bluez may be behaving differently than other socket types in this respect.

if that is so, then we have to fix the kernel. Can someone write me a simple reproducer or better send me a patch for the kernel.

Regards

Marcel

-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
Bluez-devel mailing list [email protected]
https://lists.sourceforge.net/lists/listinfo/bluez-devel

#3 lore raw

Hi All,

The attached patch makes sure that the correct error code is returned to the upper layers.
The issue with the current cvs's code is that EIO would be returned whatever the error code returned by the L2CAP layer is, as getsockopt(sk, SOL_SOCKET, SO_ERROR, ....) would never be called. The result of this patch is that you now see the reason of the failure in daemon log in case of L2CAP issue, such as:

Sep 18 10:32:53 tannat audio[16934]: avdtp_ref(0x806d230): ref=2
Sep 18 10:32:53 tannat audio[16934]: a2dp_source_request_stream: selected SEP 0x806a400
Sep 18 10:32:53 tannat audio[16934]: avdtp_ref(0x806d230): ref=3
Sep 18 10:32:53 tannat audio[16934]: stream creation in progress
Sep 18 10:33:13 tannat audio[16934]: connect(): Host is down (112)

As for the POLLOUT thing, i must say i'm confused..., and don't really see the link with the patch :-( I guess it works already as the GIOChannels heavily rely on it.

Can any of you apply this patch ?

Cheers,

Fabien

Quoted 16 lines

Hi Johan,

Quoted 5 lines
Quoted 5 lines

While trying to fix this cross case issue, i came with an issue with the way error codes are handled in avdtp.c.
The issue is basically that the part of the code that retrieves the exact error value is never executed due to premature return.

Quoted 7 lines

Looks fine to me if it works. However, I'd like to hear some comment from Marcel as well. At least my connect(2) manpage implies that a non-blocking connect should always produce a POLLOUT on connection completion regardless if the result was failure or success. So it seems bluez may be behaving differently than other socket types in this respect.

Quoted 11 lines

if that is so, then we have to fix the kernel. Can someone write me a simple reproducer or better send me a patch for the kernel.

Regards

Marcel

begin:vcard
fn:Fabien CHEVALIER
n:CHEVALIER;Fabien
org:SILICOM
adr:;;4 rue de Jouanet; RENNES ATALANTE;;35700;FRANCE email;internet:[email protected] title:Software & Studies Engineer tel;work:+33 (0) 2 99 84 17 17
version:2.1
end:vcard

#4 lore raw
Quoted 3 lines · Fabien Chevalier

As for the POLLOUT thing, i must say i'm confused..., and don't really see the link with the patch :-(
I guess it works already as the GIOChannels heavily rely on it.

GLib maps POLLOUT to G_IO_OUT, POLLHUP to G_IO_HUP, etc. I was saying that to conform to how other socket types behave[1] the callback should *not* be getting a HUP or ERR in this case but a OUT instead. As for applying the patch, I'm fine with it even though it in essence is a work-around for a kernel side problem. However, it's Marcel's call in the end.

[1] I have yet to verify this but that's what the connect(2) manpage implies (in the section about EINPROGRESS)

Johan

#5 lore raw
Quoted 11 lines · Johan Hedberg
Quoted 2 lines · Fabien Chevalier

As for the POLLOUT thing, i must say i'm confused..., and don't really see the link with the patch :-( I guess it works already as the GIOChannels heavily rely on it.

GLib maps POLLOUT to G_IO_OUT, POLLHUP to G_IO_HUP, etc. I was saying that to conform to how other socket types behave[1] the callback should *not* be getting a HUP or ERR in this case but a OUT instead. As for applying the patch, I'm fine with it even though it in essence is a work-around for a kernel side problem. However, it's Marcel's call in the end.

Quoted 2 lines

[1] I have yet to verify this but that's what the connect(2) manpage implies (in the section about EINPROGRESS)

Ok, thanks, this time i understood. :-)
I wrote a test program that does an asynchronous connect using the IP stack. (I attached the file, you can dry run yourself if you're curious ;-) ). On error we receive a revent with POLLERR value, and no POLLOUT. Conclusion is:
* POLLOUT is to be sent only when the channel is ready to send more data.
* POLLERR is the right thing to send when we cannot establish the
connection due to whatever error ==> The man page is a bit ambiguous about it.
* which means the bt kernel part is fine and does not need fixing
* which means my patch is not a workaround but a clean fix to this
bogus error returning code :-)

Marcel, Johan, if you don't have any other remarks, you would mind applying the patch ?

Cheers,

Fabien

#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <poll.h>
#include <errno.h>
#include <assert.h>
#include <fcntl.h>

int main()

{
    struct sockaddr_in addr;
    int err;
    struct pollfd pfds;

    int sock = socket(AF_INET, SOCK_STREAM, 0); 

    addr.sin_family = AF_INET;
    addr.sin_port = htons(81);
    addr.sin_addr.s_addr = inet_addr("209.85.135.104");

    fcntl(sock, F_SETFL, fcntl(sock, F_GETFL, 0) | O_NONBLOCK);

    err = connect(sock, (struct sockaddr *)&addr, sizeof(addr));
    
    assert(err == -1 && errno == EINPROGRESS);
    
    pfds.fd = sock;
    pfds.events = POLLOUT;
    
    err = poll(&pfds, 1, -1);
    assert(err == 1);
    
    printf("returned events from poll() routine:");
    if(pfds.revents & POLLOUT)
        printf("POLLOUT");
    if(pfds.revents & POLLERR)
        printf("POLLERR");

    printf("\n");    
}

begin:vcard
fn:Fabien CHEVALIER
n:CHEVALIER;Fabien
org:SILICOM
adr:;;4 rue de Jouanet; RENNES ATALANTE;;35700;FRANCE email;internet:[email protected] title:Software & Studies Engineer tel;work:+33 (0) 2 99 84 17 17
version:2.1
end:vcard