Fix a subtle bug in the poll code
This commit is contained in:
@@ -261,6 +261,7 @@ class Driver {
|
|||||||
// Copy data from the send BIO into the socket.
|
// Copy data from the send BIO into the socket.
|
||||||
//
|
//
|
||||||
// If it detects an error, sets the recent_errno flag.
|
// If it detects an error, sets the recent_errno flag.
|
||||||
|
// It is an error to call this when there is nothing in the send BIO.
|
||||||
//
|
//
|
||||||
void transfer_send_bio_to_socket(ChanInfo &chan) {
|
void transfer_send_bio_to_socket(ChanInfo &chan) {
|
||||||
if ((chan.state == CHAN_INACTIVE) || (!chan.recent_error.empty())) {
|
if ((chan.state == CHAN_INACTIVE) || (!chan.recent_error.empty())) {
|
||||||
@@ -270,7 +271,10 @@ class Driver {
|
|||||||
char *data;
|
char *data;
|
||||||
int ndata = BIO_get_mem_data(chan.send_bio, &data);
|
int ndata = BIO_get_mem_data(chan.send_bio, &data);
|
||||||
if (ndata > DRV_SHORTSTRING_SIZE) ndata = DRV_SHORTSTRING_SIZE;
|
if (ndata > DRV_SHORTSTRING_SIZE) ndata = DRV_SHORTSTRING_SIZE;
|
||||||
|
|
||||||
|
// It is an error to call this function when there is nothing in the send BIO.
|
||||||
assert(ndata > 0);
|
assert(ndata > 0);
|
||||||
|
|
||||||
std::string err;
|
std::string err;
|
||||||
int nwrote = socket_send(chan.socket, data, ndata, err);
|
int nwrote = socket_send(chan.socket, data, ndata, err);
|
||||||
// std::cerr << "chan " << chan.chid << " send " << nwrote << " err=" << err << std::endl;
|
// std::cerr << "chan " << chan.chid << " send " << nwrote << " err=" << err << std::endl;
|
||||||
@@ -453,12 +457,6 @@ class Driver {
|
|||||||
|
|
||||||
// Construct the struct pollfd vector.
|
// Construct the struct pollfd vector.
|
||||||
int pollsize = 0;
|
int pollsize = 0;
|
||||||
for (const auto &p : listen_sockets_) {
|
|
||||||
struct pollfd &pfd = pollvec_[pollsize++];
|
|
||||||
pfd.fd = p.second;
|
|
||||||
pfd.events = POLLIN;
|
|
||||||
pfd.revents = 0;
|
|
||||||
}
|
|
||||||
for (const ChanInfo &chan : chans_) {
|
for (const ChanInfo &chan : chans_) {
|
||||||
struct pollfd &pfd = pollvec_[pollsize++];
|
struct pollfd &pfd = pollvec_[pollsize++];
|
||||||
assert(chan.socket != INVALID_SOCKET);
|
assert(chan.socket != INVALID_SOCKET);
|
||||||
@@ -477,20 +475,19 @@ class Driver {
|
|||||||
mstimeout = 0;
|
mstimeout = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for (const auto &p : listen_sockets_) {
|
||||||
|
struct pollfd &pfd = pollvec_[pollsize++];
|
||||||
|
pfd.fd = p.second;
|
||||||
|
pfd.events = POLLIN;
|
||||||
|
pfd.revents = 0;
|
||||||
|
}
|
||||||
|
|
||||||
// Do the poll.
|
// Do the poll.
|
||||||
socket_poll(pollvec_.get(), pollsize, mstimeout, err);
|
socket_poll(pollvec_.get(), pollsize, mstimeout, err);
|
||||||
if_error_print_and_exit(err);
|
if_error_print_and_exit(err);
|
||||||
|
|
||||||
// Check listening sockets.
|
// Advance channels where possible and then check listen sockets.
|
||||||
int index = 0;
|
int index = 0;
|
||||||
for (auto &p : listen_sockets_) {
|
|
||||||
struct pollfd &pfd = pollvec_[index++];
|
|
||||||
if (pfd.revents & (POLLIN | POLLERR)) {
|
|
||||||
accept_connection(p.first, p.second);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Advance channels where possible.
|
|
||||||
for (ChanInfo &chan : chans_) {
|
for (ChanInfo &chan : chans_) {
|
||||||
struct pollfd &pfd = pollvec_[index++];
|
struct pollfd &pfd = pollvec_[index++];
|
||||||
if ((pfd.revents & POLLIN) != 0) {
|
if ((pfd.revents & POLLIN) != 0) {
|
||||||
@@ -513,6 +510,12 @@ class Driver {
|
|||||||
chan.nbytes = 0;
|
chan.nbytes = 0;
|
||||||
chan.bytes = 0;
|
chan.bytes = 0;
|
||||||
}
|
}
|
||||||
|
for (auto &p : listen_sockets_) {
|
||||||
|
struct pollfd &pfd = pollvec_[index++];
|
||||||
|
if (pfd.revents & (POLLIN | POLLERR)) {
|
||||||
|
accept_connection(p.first, p.second);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Delete any newly-inactive channels
|
// Delete any newly-inactive channels
|
||||||
drvutil::remove_marked_items(chans_);
|
drvutil::remove_marked_items(chans_);
|
||||||
|
|||||||
Reference in New Issue
Block a user