NetBSD-Bugs archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
kern/59056: poll POLLHUP bugs
>Number:         59056
>Category:       kern
>Synopsis:       poll POLLHUP bugs
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    kern-bug-people
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Fri Feb 07 19:40:01 +0000 2025
>Originator:     Taylor R Campbell
>Release:        
>Organization:
The NotPolleD Foundation
>Environment:
>Description:
If you open a {pipe, socketpair} and close the read side (either side for socket pair), polling the write side for POLLOUT returns:
- POLLHUP|POLLOUT, for pipe;
- POLLOUT, for socketpair.
The pipe case is wrong because POLLHUP and POLLOUT are mutually exclusive in POSIX:
POLLHUP
    A device has been disconnected, or a pipe or FIFO has been closed by the last process that had it open for writing. [...] This event and POLLOUT are mutually-exclusive; a stream can never be writable if a hangup has occurred.
https://pubs.opengroup.org/onlinepubs/9699919799/functions/poll.html
The socketpair is also wrong because any attempt to write to the socket triggers SIGPIPE/EPIPE, so surely POLLHUP must be set for it.
>How-To-Repeat:
#include <sys/socket.h>
#include <err.h>
#include <poll.h>
#include <signal.h>
#include <stdio.h>
#include <unistd.h>
static void
ignoresig(int signo)
{
}
int
main(void)
{
	int s[2];
	struct pollfd pfd;
	int i, nfds;
	if (signal(SIGPIPE, ignoresig) == SIG_ERR)
		err(1, "signal(SIGPIPE)");
	if (socketpair(AF_LOCAL, SOCK_STREAM, 0, s) == -1)
		err(1, "socketpair");
//	if (pipe(s) == -1)
//		err(1, "pipe");
	pfd = (struct pollfd){ .fd = s[1], .events = POLLOUT };
	nfds = poll(&pfd, 1, 0);
	if (nfds == -1)
		err(1, "poll");
	printf("nfds=%d\n", nfds);
	printf("[%d] .fd=%d .revents=0x%x\n", 0, pfd.fd, pfd.revents);
	if (close(s[0]) == -1)
		err(1, "close");
	pfd = (struct pollfd){ .fd = s[1], .events = POLLOUT };
	nfds = poll(&pfd, 1, 0);
	if (nfds == -1)
		err(1, "poll");
	printf("nfds=%d\n", nfds);
	printf("[%d] .fd=%d .revents=0x%x\n", 0, pfd.fd, pfd.revents);
	fflush(stdout);
	char ch = 0;
	if (write(s[1], &ch, 1) == -1)
		err(1, "write");
	return ferror(stdout);
}
>Fix:
Yes, please!
Home |
Main Index |
Thread Index |
Old Index