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); }