Hi,
When running my pf regression tests, I triggered netcat hanging in
write(2). This is bit strange as poll(2) should check that the socket
is writeable. However making the network socket non-blocking
keeps the data flowing. Note that the code to handle EAGAIN is
already there.
To trigger the blocking write(2) I use:
openssl rand 200000 | nc -N tcp-echo-server 7 | wc -c | grep 200000$
Ktrace shows that it happens from time to time:
11789 nc CALL poll(0x7f7ffffbd5e0,4,INFTIM)
11789 nc RET poll 2
11789 nc CALL write(3,0x7f7ffffbd610,0x4000)
11789 nc RET write -1 errno 35 Resource temporarily unavailable
11789 nc CALL read(3,0x7f7ffffc1610,0x4000)
11789 nc GIO fd 3 read 2048 bytes
ok?
bluhm
Index: usr.bin/nc/netcat.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/usr.bin/nc/netcat.c,v
retrieving revision 1.130
diff -u -p -r1.130 netcat.c
--- usr.bin/nc/netcat.c 26 Jul 2015 19:12:28 -0000 1.130
+++ usr.bin/nc/netcat.c 17 Aug 2015 07:25:30 -0000
@@ -95,7 +95,7 @@ int Sflag; /* TCP MD5
signature opti
int Tflag = -1; /* IP Type of Service */
int rtableid = -1;
-int timeout = -1;
+int timeout = INFTIM;
int family = AF_UNSPEC;
char *portlist[PORT_MAX+1];
char *unix_dg_tmp_socket;
@@ -397,8 +397,8 @@ main(int argc, char *argv[])
readwrite(s);
} else {
len = sizeof(cliaddr);
- connfd = accept(s, (struct sockaddr *)&cliaddr,
- &len);
+ connfd = accept4(s, (struct sockaddr *)&cliaddr,
+ &len, SOCK_NONBLOCK);
if (connfd == -1) {
/* For now, all errnos are fatal */
err(1, "accept");
@@ -594,8 +594,8 @@ remote_connect(const char *host, const c
res0 = res;
do {
- if ((s = socket(res0->ai_family, res0->ai_socktype,
- res0->ai_protocol)) < 0)
+ if ((s = socket(res0->ai_family, res0->ai_socktype |
+ SOCK_NONBLOCK, res0->ai_protocol)) < 0)
continue;
if (rtableid >= 0 && (setsockopt(s, SOL_SOCKET, SO_RTABLE,
@@ -644,15 +644,9 @@ timeout_connect(int s, const struct sock
{
struct pollfd pfd;
socklen_t optlen;
- int flags, optval;
+ int optval;
int ret;
- if (timeout != -1) {
- flags = fcntl(s, F_GETFL, 0);
- if (fcntl(s, F_SETFL, flags | O_NONBLOCK) == -1)
- err(1, "set non-blocking mode");
- }
-
if ((ret = connect(s, name, namelen)) != 0 && errno == EINPROGRESS) {
pfd.fd = s;
pfd.events = POLLOUT;
@@ -669,9 +663,6 @@ timeout_connect(int s, const struct sock
} else
err(1, "poll failed");
}
-
- if (timeout != -1 && fcntl(s, F_SETFL, flags) == -1)
- err(1, "restoring flags");
return (ret);
}