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