lkml.org 
[lkml]   [2004]   [Nov]   [17]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    /
    From
    SubjectRe: AF_UNIX sockets: strange behaviour
    Date
    On Wed, 17 Nov 2004 16:29:14 +0100 (CET)
    Catalin Drula <Catalin.Drula@imag.fr> wrote:

    > Hi,
    >
    > I have a small application that communicates over Bluetooth. I use
    > connection-oriented UNIX domain sockets (AF_UNIX, SOCK_STREAM) to
    > communicate between the applications's threads. When reading from
    > one of these sockets, I get a strange behaviour: if I read all the
    > bytes that are available (13, in this case) all at once, it's fine;
    > however, if I try to read in two smaller batches (say, first time
    > 6, and second time 7), the first read returns (with the 6 bytes), but
    > the second read never returns.
    >
    > As far as I know, this is not expected behaviour for SOCK_STREAM sockets.
    > I tried looking into the problem so I instrumented net/unix/af_unix.c to
    > see what is going on. More specifically, I was focusing on the function
    > unix_stream_recvmsg. Here is what I noticed:
    >
    > - there is a skb in the sk_receive_queue with a len of 13
    > - 6 bytes are read from it
    > - a skb with the remaining 7 bytes is requeued in sk_receive_queue
    > - on the next call to unix_stream_recvmsg, the sk_receive_queue is
    > empty (!)
    >
    > Thus, this confirms the behaviour observed from userspace. Is this a bug?
    > Who could be removing the skb from the receive_queue?
    >
    > Thanks for any ideas/suggestions,
    >
    > Catalin
    >

    See the following, it doesn't seem to be a problem (this is on 2.6.10-rc2)

    /* Unix domain socket buffer test */
    #include <unistd.h>
    #include <stdio.h>
    #include <sys/socket.h>
    #include <sys/un.h>

    static void client(const char *path, const char *msg) {
    int s, len = strlen(msg);
    static struct sockaddr_un sun = { .sun_family = AF_UNIX };

    s = socket(AF_UNIX, SOCK_STREAM, 0);
    if (s < 0) { perror("socket"); return; }

    strncpy(sun.sun_path, path, sizeof(sun.sun_path));
    if (connect(s, (struct sockadr *)&sun, sizeof(sun)) < 0) {
    perror("connect");
    return;
    }

    if (write(s, msg, len) != len)
    perror("write");
    close(s);
    }


    static void server(int s) {
    struct sockaddr_un nsun;
    int len = sizeof(nsun);
    int ns = accept(s, (struct sockaddr *) &nsun, &len);
    int cc;
    char buf[3];

    if (ns < 0) {
    perror("accept");
    return;
    }

    while ((cc = read(ns, buf, sizeof(buf))) > 0)
    write(1, buf, cc);

    putchar('\n');

    if (cc < 0)
    perror("read request");

    if (write(ns, "done", 4) != 4)
    perror("write response");
    }

    int main(int argc, char **argv) {
    int s;
    static struct sockaddr_un sun = { .sun_family = AF_UNIX };

    if (argc != 3) { fprintf(stderr, "Usage: udtest name message\n"); return 1; }

    s = socket(AF_UNIX, SOCK_STREAM, 0);
    if (s < 0) { perror("socket"); return 1; }

    strncpy(sun.sun_path, argv[1], sizeof(sun.sun_path));
    if (bind(s, (struct sockaddr *) &sun, sizeof(sun)) < 0) {
    perror("bind"); return 1;
    }

    listen(s, 1);

    if (fork() == 0) {
    close(s);
    client(sun.sun_path, argv[2]);
    } else {
    server(s);
    close(s);
    unlink(sun.sun_path);
    }
    return 0;
    }

    -
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at http://www.tux.org/lkml/

    \
     
     \ /
      Last update: 2005-03-22 14:08    [W:7.118 / U:0.012 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site