Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F142405520
D29757.id87420.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
4 KB
Referenced Files
None
Subscribers
None
D29757.id87420.diff
View Options
Index: lib/libc/sys/poll.2
===================================================================
--- lib/libc/sys/poll.2
+++ lib/libc/sys/poll.2
@@ -126,6 +126,15 @@
should never be present in the
.Fa revents
bitmask at the same time.
+.It POLLRDHUP
+Remote peer closed connection, or shut down writing.
+Unlike
+POLLHUP,
+POLLRDHUP
+must be present in the
+.Fa events
+bitmask to be reported.
+Applies only to stream sockets.
.It POLLNVAL
The file descriptor is not open,
or in capability mode the file descriptor has insufficient rights.
@@ -261,6 +270,9 @@
The
.Fn ppoll
is not specified by POSIX.
+The
+POLLRD
+flag is not specified by POSIX, but is compatible with Linux.
.Sh HISTORY
The
.Fn poll
Index: sys/kern/uipc_socket.c
===================================================================
--- sys/kern/uipc_socket.c
+++ sys/kern/uipc_socket.c
@@ -3562,14 +3562,14 @@
revents |= events & (POLLPRI | POLLRDBAND);
if ((events & POLLINIGNEOF) == 0) {
if (so->so_rcv.sb_state & SBS_CANTRCVMORE) {
- revents |= events & (POLLIN | POLLRDNORM);
+ revents |= events & (POLLIN | POLLRDNORM | POLLRDHUP);
if (so->so_snd.sb_state & SBS_CANTSENDMORE)
revents |= POLLHUP;
}
}
if (revents == 0) {
if (events &
- (POLLIN | POLLPRI | POLLRDNORM | POLLRDBAND)) {
+ (POLLIN | POLLPRI | POLLRDNORM | POLLRDBAND | POLLRDHUP)) {
selrecord(td, &so->so_rdsel);
so->so_rcv.sb_flags |= SB_SEL;
}
Index: sys/sys/poll.h
===================================================================
--- sys/sys/poll.h
+++ sys/sys/poll.h
@@ -71,6 +71,7 @@
#if __BSD_VISIBLE
/* General FreeBSD extension (currently only supported for sockets): */
#define POLLINIGNEOF 0x2000 /* like POLLIN, except ignore EOF */
+#define POLLRDHUP 0x4000 /* half shut down */
#endif
/*
Index: tests/sys/netinet/socket_afinet.c
===================================================================
--- tests/sys/netinet/socket_afinet.c
+++ tests/sys/netinet/socket_afinet.c
@@ -25,6 +25,7 @@
* SUCH DAMAGE.
*/
+#include <poll.h>
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
@@ -89,12 +90,91 @@
close(sd);
}
+ATF_TC_WITHOUT_HEAD(socket_afinet_poll_rdhup);
+ATF_TC_BODY(socket_afinet_poll_rdhup, tc)
+{
+ int ss, ss2, cs, rc;
+ struct sockaddr_in sin;
+ struct pollfd pfd;
+ char buffer;
+ int one = 1;
+
+ ss = socket(PF_INET, SOCK_STREAM, 0);
+ ATF_CHECK(ss >= 0);
+
+ rc = setsockopt(ss, SOL_SOCKET, SO_REUSEPORT, &one, sizeof(one));
+ ATF_CHECK_EQ(0, rc);
+
+ bzero(&sin, sizeof(sin));
+ sin.sin_family = AF_INET;
+ sin.sin_len = sizeof(sin);
+ sin.sin_port = htons(6666);
+ sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+ rc = bind(ss, (struct sockaddr *)&sin, sizeof(sin));
+ ATF_CHECK_EQ(0, rc);
+
+ rc = listen(ss, 1);
+ ATF_CHECK_EQ(0, rc);
+
+ cs = socket(PF_INET, SOCK_STREAM, 0);
+ ATF_CHECK(cs >= 0);
+ rc = connect(cs, (struct sockaddr *)&sin, sizeof(sin));
+ ATF_CHECK_EQ(0, rc);
+
+ ss2 = accept(ss, NULL, NULL);
+ ATF_CHECK(ss2 >= 0);
+
+ /* Server can write, so sees POLLOUT. */
+ pfd.fd = ss2;
+ pfd.events = POLLIN | POLLOUT | POLLRDHUP;
+ rc = poll(&pfd, 1, 0);
+ ATF_CHECK_EQ(1, rc);
+ ATF_CHECK_EQ(POLLOUT, pfd.revents);
+
+ /* Client writes too bytes, server reads only one of them. */
+ rc = write(cs, "xx", 2);
+ ATF_CHECK_EQ(2, rc);
+ rc = read(ss2, &buffer, 1);
+ ATF_CHECK_EQ(1, rc);
+
+ /* Server can read, so sees POLLIN. */
+ pfd.fd = ss2;
+ pfd.events = POLLIN | POLLOUT | POLLRDHUP;
+ rc = poll(&pfd, 1, 0);
+ ATF_CHECK_EQ(1, rc);
+ ATF_CHECK_EQ(POLLIN | POLLOUT, pfd.revents);
+
+ /* Client closes socket! */
+ rc = close(cs);
+ ATF_CHECK_EQ(0, rc);
+
+ /*
+ * Server sees Linux-style POLLRDHUP. Note that this is the case even
+ * though one byte of data remains unread.
+ *
+ * This races against the delivery of FIN caused by the close() above.
+ * Sometimes (more likely when run under truss or if another system
+ * call is added in between) it hits the path where sopoll_generic()
+ * immediately sees SBS_CANTRCVMORE, and sometimes it sleeps with flag
+ * SB_SEL so that it's woken up almost immediately and runs again,
+ * which is why we need a non-zero timeout here.
+ */
+ pfd.fd = ss2;
+ pfd.events = POLLRDHUP;
+ rc = poll(&pfd, 1, 60000);
+ ATF_CHECK_EQ(1, rc);
+ ATF_CHECK_EQ(POLLRDHUP, pfd.revents);
+
+ close(ss);
+}
+
ATF_TP_ADD_TCS(tp)
{
ATF_TP_ADD_TC(tp, socket_afinet);
ATF_TP_ADD_TC(tp, socket_afinet_bind_zero);
ATF_TP_ADD_TC(tp, socket_afinet_bind_ok);
+ ATF_TP_ADD_TC(tp, socket_afinet_poll_rdhup);
return atf_no_error();
}
Index: usr.bin/truss/syscalls.c
===================================================================
--- usr.bin/truss/syscalls.c
+++ usr.bin/truss/syscalls.c
@@ -726,7 +726,7 @@
static struct xlat poll_flags[] = {
X(POLLSTANDARD) X(POLLIN) X(POLLPRI) X(POLLOUT) X(POLLERR)
X(POLLHUP) X(POLLNVAL) X(POLLRDNORM) X(POLLRDBAND)
- X(POLLWRBAND) X(POLLINIGNEOF) XEND
+ X(POLLWRBAND) X(POLLINIGNEOF) X(POLLRDHUP) XEND
};
static struct xlat sigaction_flags[] = {
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Tue, Jan 20, 4:49 PM (10 h, 43 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
27766082
Default Alt Text
D29757.id87420.diff (4 KB)
Attached To
Mode
D29757: POLLRDHUP
Attached
Detach File
Event Timeline
Log In to Comment