Fix incorrect dispatch of poll events when more than one peer is present

This commit is contained in:
Kovid Goyal 2022-06-04 09:26:57 +05:30
parent 762dd065f3
commit 835cb31501
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C

View File

@ -1416,7 +1416,7 @@ io_loop(void *data) {
typedef struct {
id_type id;
size_t num_of_unresponded_messages_sent_to_main_thread;
size_t num_of_unresponded_messages_sent_to_main_thread, fd_array_idx;
bool finished_reading;
int fd;
struct {
@ -1603,13 +1603,14 @@ talk_loop(void *data) {
for (size_t i = 0; i < talk_data.num_peers; i++) {
Peer *p = talk_data.peers + i;
if (!p->read.finished || p->write.used) {
fds[num_listen_fds + num_peer_fds].fd = p->fd;
fds[num_listen_fds + num_peer_fds].revents = 0;
p->fd_array_idx = num_listen_fds + num_peer_fds++;
fds[p->fd_array_idx].fd = p->fd;
fds[p->fd_array_idx].revents = 0;
int flags = 0;
if (!p->read.finished) flags |= POLLIN;
if (p->write.used) flags |= POLLOUT;
fds[num_listen_fds + num_peer_fds++].events = flags;
}
fds[p->fd_array_idx].events = flags;
} else p->fd_array_idx = 0;
}
talk_mutex(unlock);
}
@ -1624,13 +1625,16 @@ talk_loop(void *data) {
if (fds[num_listen_fds - 1].revents & POLLIN) {
drain_fd(fds[num_listen_fds - 1].fd); // wakeup
}
for (size_t i = num_listen_fds, k = 0; i < num_peer_fds + num_listen_fds; i++, k++) {
for (size_t k = 0; k < talk_data.num_peers; k++) {
Peer *p = talk_data.peers + k;
if (fds[i].revents & (POLLIN | POLLHUP)) read_from_peer(self, p);
if (fds[i].revents & POLLOUT) write_to_peer(p);
if (fds[i].revents & POLLNVAL) {
p->read.finished = true;
p->write.failed = true; p->write.used = 0;
if (p->fd_array_idx) {
if (fds[p->fd_array_idx].revents & (POLLIN | POLLHUP)) read_from_peer(self, p);
if (fds[p->fd_array_idx].revents & POLLOUT) write_to_peer(p);
if (fds[p->fd_array_idx].revents & POLLNVAL) {
p->read.finished = true;
p->write.failed = true; p->write.used = 0;
}
break;
}
}
} else if (ret < 0) { if (errno != EAGAIN && errno != EINTR) perror("poll() on talk fds failed"); }