using unix domain socket get ENOTCONN in both 6.2 and 7.0

From: Deng XueFeng <dengxf_at_gmail.com>
Date: Mon, 17 Sep 2007 16:12:41 +0800
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_at_gmail.com>
Received on Mon Sep 17 2007 - 06:40:46 UTC

This archive was generated by hypermail 2.4.0 : Wed May 19 2021 - 11:39:17 UTC