Date: Mon, 17 Sep 2007 16:12:41 +0800 From: Deng XueFeng <dengxf@gmail.com> To: freebsd-current@freebsd.org Subject: using unix domain socket get ENOTCONN in both 6.2 and 7.0 Message-ID: <20070917160248.003B.DENGXF@gmail.com>
next in thread | raw e-mail | index | archive | help
today, when I trace some performance issue about my streaming server.
I found a strange thing in domain socket.
when read from a domain socket(created by socketpair,and write/read some times).
read return -1, and errno = ENOTCONN (Socket is not connected.)
then I write a test program, and can reproduce in 6.2 and 7.0
but not each time will get ENOTCONN.
thanks.
#./ud_test
child recv len [4992] failed: Unknown error: 0
main send len [-1] failed: Socket is not connected
/*
 *
 * gcc -Wall -Werror -o ud_test ud_test.c
 *
 */
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>
#include <fcntl.h>
int ud[2];
int child(void)
{
    int fd;
    char buf[8193];
    int ret;
    int flag;
    int err;
    fd = ud[1];
    flag = fcntl(fd, F_GETFL);
    fcntl(fd, flag | O_NONBLOCK);
    while (1)
    {
        ret = read(fd, buf, sizeof(buf));
        if (ret == 0)
        {
            usleep(100*1000);
            continue;
        }
        if (ret != sizeof(buf))
        {
            err = errno;
            close(fd);
            printf("child recv len [%d] failed: %s\n", ret, strerror(err));
            exit(1);
        }
        memset(buf, 'B', sizeof(buf));
        ret = write(fd, buf, sizeof(buf));
        if (ret != sizeof(buf))
        {
            err = errno;
            close(fd);
            printf("child send len [%d] failed: %s\n", ret, strerror(err));
            exit(1);
        }
    }
    return 0;
}
int start_child(void)
{
    pid_t pid;
    pid = fork();
    if (pid == -1)
    {
        perror("fork failed");
        return (-1);
    }
    else if (pid == 0)
    {
        close(ud[0]);
        child();
        exit(1);
    }
    else
    {
        close(ud[1]);
        return (0);
    }
}
int test_main(void)
{
    int fd = ud[0];
    int ret;
    char buf[8193];
    int flag;
    int err;
    flag = fcntl(fd, F_GETFL);
    fcntl(fd, flag | O_NONBLOCK);
    while (1)
    {
        memset(buf, 'A', sizeof(buf));
        ret = write(fd, buf, sizeof(buf));
        if (ret != sizeof(buf))
        {
            err = errno;
            close(fd);
            printf("main send len [%d] failed: %s\n", ret, strerror(err));
            exit(1);
        }
        ret = read(fd, buf, sizeof(buf));
        if (ret != sizeof(buf))
        {
            err = errno;
            close(fd);
            printf("main recv len [%d] failed: %s\n", ret, strerror(err));
            exit(1);
        }
    }
    return (0);
}
int main(void)
{
    int ret;
    ret = socketpair(AF_UNIX, SOCK_STREAM, 0, &ud[0]);
    if (ret < 0)
    {
        printf("socketpair failed: %s\n", strerror(errno));
        exit(1);
    }
    if (start_child() != 0)
    {
        return 1;
    }
    /* Let the child process get the socket established */
    sleep(2);
    test_main();
    puts("Parent process finished.");
    return 0;
}
-- 
Deng XueFeng <dengxf@gmail.com>
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20070917160248.003B.DENGXF>
