Call for testing: OpenSSH-5.9

Carson Gaspar carson at taltos.org
Sat Sep 3 06:21:17 EST 2011


On 9/2/11 5:33 AM, Darren Tucker wrote:
> On Mon, Aug 29, 2011 at 6:31 PM, Darren Tucker<dtucker at zip.com.au>  wrote:
>> On Mon, Aug 29, 2011 at 2:48 PM, Darren Tucker<dtucker at zip.com.au>  wrote:
>> [...]
>>> confirmed: it's poll.
>>
>> Actually now I'm not sure about that.  Or rather I still think it's
>> poll, but maybe not in the place I originally thought.
>
> OK, I think I have it figured out.  Here's my theory:
>
> 1. it's poll()
> 2. some platforms (eg Solaris) implement select() on top of poll().
> Those are the ones where the test fails.
> 3. platforms that implement select() natively (eg Linux) are the ones that work.
> 4. the problem is not in atomicio, because poll is only used to
> prevent busy-waiting on EAGAIN.  if poll() fails it'll busy-wait on
> EAGAIN but otherwise work.  rather, the failure is in the main select
> loop.

It's pollsys(), called by both poll() and select() in Solaris 10, so the 
failure is in the kernel (looking at the source, it's in poll_common - 
"if (nfds > p->p_fno_ctl)"). One option is to use /dev/poll directly, 
working around the issue. The code is more complex, but not impossibly so.

#include <sys/types.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <sys/select.h>
#include <sys/socket.h>
#include <stdio.h>
#include <poll.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/devpoll.h>
#include <strings.h>
#include <unistd.h>
#include <stdlib.h>

int main(int argc, char **argv)
{
         struct rlimit rl_zero;
         struct pollfd pfd;
         int wfd, r, enforce_limit = 0;
         struct pollfd fds[1];
         dvpoll_t dopoll;

         if (argc == 2 && strcmp(argv[1], "limit") == 0)
                 enforce_limit = 1;

         fds[0].fd = open("/dev/null", O_RDONLY);
         fds[0].events = POLLIN;
         fds[0].revents = 0;

         dopoll.dp_timeout = 0;
         dopoll.dp_nfds = 1;
         dopoll.dp_fds = (struct pollfd *)
                 malloc(sizeof(struct pollfd));
         if (!dopoll.dp_fds) {
                 perror("Failed in dopoll.dp_fds" );
                 exit(-1);
         }

         if ((wfd = open("/dev/poll", O_RDWR)) < 0) {
                 perror("Failed to open /dev/poll");
                 exit(-1);
         }

         if (write(wfd, &fds[0], sizeof(struct pollfd)) != sizeof(struct 
pollfd)) {
                 perror("failed to write all pollfds");
                 close(wfd);
                 exit(-1);
         }

         if (enforce_limit) {
                 rl_zero.rlim_cur = rl_zero.rlim_max = 0;
                 setrlimit(RLIMIT_FSIZE, &rl_zero);
                 setrlimit(RLIMIT_NOFILE, &rl_zero);
         }

         r = ioctl(wfd, DP_POLL, &dopoll);
         printf("/dev/poll = %d, error: %s\n", r, strerror(errno));
}



More information about the openssh-unix-dev mailing list