mirror of
https://git.tartarus.org/simon/putty.git
synced 2025-01-10 09:58:01 +00:00
pollwrap: stop returning unasked-for rwx statuses.
The sets of poll(2) events that we check in order to return SELECT_R and SELECT_W overlap: to be precise, they have POLLERR in common. So if an fd signals POLLERR, then pollwrap_get_fd_rwx will respond by saying that it has both SELECT_R and SELECT_W available on it - even if the caller had only asked for one of those. In other words, you can get a spurious SELECT_W notification on an fd that you never asked for SELECT_W on in the first place. This definitely isn't what I'd meant that API to do. In particular, if a socket in the middle of an asynchronous connect() signals POLLERR, then Unix Plink will call select_result for it with SELECT_R and then SELECT_W respectively. The former will notice that it's got an error condition and call plug_closing - and _then_ the latter will decide that it's writable and set s->connected! The plan was to only select it for write until it was connected, but this bug in pollwrap was defeating that plan. Now pollwrap_get_fd_rwx should only ever return a set of rwx flags that's a subset of the one that the client asked for via pollwrap_add_fd_rwx.
This commit is contained in:
parent
bf0f323fb4
commit
78974fce89
@ -126,29 +126,44 @@ int pollwrap_poll_timeout(pollwrapper *pw, int milliseconds)
|
|||||||
return poll(pw->fds, pw->nfd, milliseconds);
|
return poll(pw->fds, pw->nfd, milliseconds);
|
||||||
}
|
}
|
||||||
|
|
||||||
int pollwrap_get_fd_events(pollwrapper *pw, int fd)
|
static void pollwrap_get_fd_events_revents(pollwrapper *pw, int fd,
|
||||||
|
int *events_p, int *revents_p)
|
||||||
{
|
{
|
||||||
pollwrap_fdtopos *f2p, f2p_find;
|
pollwrap_fdtopos *f2p, f2p_find;
|
||||||
|
int events = 0, revents = 0;
|
||||||
|
|
||||||
assert(fd >= 0);
|
assert(fd >= 0);
|
||||||
|
|
||||||
f2p_find.fd = fd;
|
f2p_find.fd = fd;
|
||||||
f2p = find234(pw->fdtopos, &f2p_find, NULL);
|
f2p = find234(pw->fdtopos, &f2p_find, NULL);
|
||||||
if (!f2p)
|
if (f2p) {
|
||||||
return 0;
|
events = pw->fds[f2p->pos].events;
|
||||||
|
revents = pw->fds[f2p->pos].revents;
|
||||||
|
}
|
||||||
|
|
||||||
return pw->fds[f2p->pos].revents;
|
if (events_p)
|
||||||
|
*events_p = events;
|
||||||
|
if (revents_p)
|
||||||
|
*revents_p = revents;
|
||||||
|
}
|
||||||
|
|
||||||
|
int pollwrap_get_fd_events(pollwrapper *pw, int fd)
|
||||||
|
{
|
||||||
|
int revents;
|
||||||
|
pollwrap_get_fd_events_revents(pw, fd, NULL, &revents);
|
||||||
|
return revents;
|
||||||
}
|
}
|
||||||
|
|
||||||
int pollwrap_get_fd_rwx(pollwrapper *pw, int fd)
|
int pollwrap_get_fd_rwx(pollwrapper *pw, int fd)
|
||||||
{
|
{
|
||||||
int revents = pollwrap_get_fd_events(pw, fd);
|
int events, revents;
|
||||||
|
pollwrap_get_fd_events_revents(pw, fd, &events, &revents);
|
||||||
int rwx = 0;
|
int rwx = 0;
|
||||||
if (revents & SELECT_R_OUT)
|
if ((events & POLLIN) && (revents & SELECT_R_OUT))
|
||||||
rwx |= SELECT_R;
|
rwx |= SELECT_R;
|
||||||
if (revents & SELECT_W_OUT)
|
if ((events & POLLOUT) && (revents & SELECT_W_OUT))
|
||||||
rwx |= SELECT_W;
|
rwx |= SELECT_W;
|
||||||
if (revents & SELECT_X_OUT)
|
if ((events & POLLPRI) && (revents & SELECT_X_OUT))
|
||||||
rwx |= SELECT_X;
|
rwx |= SELECT_X;
|
||||||
return rwx;
|
return rwx;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user