NetBSD-Bugs archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

kern/54158: poll(2) does not allow polling all possible fds (hardcoded limit to ~1000+ fds)



>Number:         54158
>Category:       kern
>Synopsis:       poll(2) does not allow polling all possible fds (hardcoded limit to ~1000+ fds)
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    kern-bug-people
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Sat May 04 14:05:00 +0000 2019
>Originator:     Anthony Mallet
>Release:        -current
>Organization:
>Environment:
NetBSD ficus 8.99.37 NetBSD 8.99.37 (FICUS) #18: Sat Apr 27 15:54:05 WEST 2019
>Description:
Trying to poll a bit more than 1000 file descriptors returns EINVAL.
I think this basically comes from the test in pollcommon(), in
kern/sys_select.c, that does this:

if (nfds > 1000 + curlwp->l_fd->fd_dt->dt_nfiles)
	return EINVAL;

I have a modified login.conf that allows for 1024 descriptors, but poll(&fds, 1024, 0) always fails.

I came accross this issue while tracking down bugs in a real software,
so this is not a theoretical bug report :) Attached is a sample test
program that exhibit the issue.
(the idea of the code is to count open fds)

Maybe the test in pollcommon() should be based on the current hard limit?

>How-To-Repeat:
# cat poll.c
#include <sys/poll.h>
#include <sys/resource.h>
#include <err.h>
#include <stdio.h>
#include <stdlib.h>

int
main()
{
  struct rlimit limit;
  struct pollfd *pollfds;
  size_t i, free_fds;

  if (getrlimit(RLIMIT_NOFILE, &limit)) err(2, "getrlimit()");
  if (limit.rlim_cur == RLIM_INFINITY) errx(2, "too many");

  printf("descriptors: %d\n", limit.rlim_cur);

  pollfds = calloc(limit.rlim_cur, sizeof(*pollfds));
  if (!pollfds) err(2, "calloc");
  for (i = 0; i < limit.rlim_cur; i++) {
    pollfds[i].fd = i;
    pollfds[i].events = 0;
  }

  if (poll(pollfds, limit.rlim_cur, 0) == -1) err(2, "poll()");

  free_fds = 0;
  for (i = 0; i < limit.rlim_cur; i++) {
    if (pollfds[i].revents & POLLNVAL) free_fds++;
  }

  printf("free fds: %zu\n", free_fds);
  return 0;
}
# gcc -o poll poll.c
# ./poll
descriptors: 1024
poll: poll(): Invalid argument

>Fix:




Home | Main Index | Thread Index | Old Index