This is the mail archive of the
cygwin
mailing list for the Cygwin project.
non-blocking accept() can hang.
- From: Tanaka Akira <akr at fsij dot org>
- To: cygwin at cygwin dot com
- Date: Tue, 5 Feb 2013 15:39:39 +0900
- Subject: non-blocking accept() can hang.
Hi.
I found that non-blocking accept() can hang.
The following test program shows the problem.
% uname -mrsv
CYGWIN_NT-5.1 1.7.17(0.262/5/3) 2012-10-19 14:39 i686
% cat tst-nonblocking.c
#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <sys/un.h>
void set_nonblock(int fd)
{
int ret;
ret = fcntl(fd, F_GETFL);
if (ret == -1) { perror("fcntl(F_GETFL)"); exit(EXIT_FAILURE); }
ret |= O_NONBLOCK;
ret = fcntl(fd, F_SETFL, ret);
if (ret == -1) { perror("fcntl(F_SETFL)"); exit(EXIT_FAILURE); }
}
int main(int argc, char *argv[])
{
int s, c, ret;
struct sockaddr_un addr;
socklen_t addrlen;
unlink("socketfile");
addrlen = sizeof(addr);
memset(&addr, '\0', addrlen);
addr.sun_family = AF_UNIX;
strcpy(addr.sun_path, "socketfile");
s = socket(AF_UNIX, SOCK_STREAM, 0);
if (s == -1) { perror("socket(server)"); exit(EXIT_FAILURE); }
set_nonblock(s);
ret = bind(s, (struct sockaddr *)&addr, addrlen);
if (ret == -1) { perror("bind"); exit(EXIT_FAILURE); }
ret = listen(s, SOMAXCONN);
if (ret == -1) { perror("listen"); exit(EXIT_FAILURE); }
c = socket(AF_UNIX, SOCK_STREAM, 0);
if (c == -1) { perror("socket(client)"); exit(EXIT_FAILURE); }
set_nonblock(c);
ret = connect(c, (struct sockaddr *)&addr, addrlen);
if (ret == -1 && errno == EINPROGRESS) { perror("connect"); }
else if (ret == -1) { perror("connect"); exit(EXIT_FAILURE); }
ret = accept(s, NULL, 0);
if (ret == -1) { perror("accept"); exit(EXIT_FAILURE); }
return EXIT_SUCCESS;
}
% gcc -Wall tst-nonblocking.c -o tst-nonblocking
% ./tst-nonblocking
connect: Operation now in progress
(^C and ^Z is not effective. I used Windows task manager to kill
the process.)
I found this problem when I investigate why the following program blocks.
The following program doesn't use O_NONBLOCK but other OS (GNU/Linux,
FreeBSD, NetBSD, OpenBSD and SunOS) doesn't block.
Is it intentional behavior?
% cat tst-blocking.c
#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <sys/un.h>
int main(int argc, char *argv[])
{
int s, c, ret;
struct sockaddr_un addr;
socklen_t addrlen;
unlink("socketfile");
addrlen = sizeof(addr);
memset(&addr, '\0', addrlen);
addr.sun_family = AF_UNIX;
strcpy(addr.sun_path, "socketfile");
s = socket(AF_UNIX, SOCK_STREAM, 0);
if (s == -1) { perror("socket(server)"); exit(EXIT_FAILURE); }
ret = bind(s, (struct sockaddr *)&addr, addrlen);
if (ret == -1) { perror("bind"); exit(EXIT_FAILURE); }
ret = listen(s, SOMAXCONN);
if (ret == -1) { perror("listen"); exit(EXIT_FAILURE); }
c = socket(AF_UNIX, SOCK_STREAM, 0);
if (c == -1) { perror("socket(client)"); exit(EXIT_FAILURE); }
ret = connect(c, (struct sockaddr *)&addr, addrlen);
if (ret == -1 && errno == EINPROGRESS) { perror("connect"); }
else if (ret == -1) { perror("connect"); exit(EXIT_FAILURE); }
return EXIT_SUCCESS;
}
% gcc -Wall tst-nonblocking.c -o tst-nonblocking
% ./tst-blocking
(^C can interrupt the process.)
--
Tanaka Akira
--
Problem reports: http://cygwin.com/problems.html
FAQ: http://cygwin.com/faq/
Documentation: http://cygwin.com/docs.html
Unsubscribe info: http://cygwin.com/ml/#unsubscribe-simple