using unix domain socket get ENOTCONN in both 6.2 and 7.0
Deng XueFeng
dengxf at gmail.com
Mon Sep 17 01:40:46 PDT 2007
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>
More information about the freebsd-current
mailing list