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