Commit b55a98946f9837e22e8a2cdad22147f1c5ab822e
1 parent
940d7edc
Fix readiness race condition
Showing
1 changed file
with
13 additions
and
9 deletions
client.cpp
| ... | ... | @@ -354,17 +354,16 @@ void Client::setReadyForWriting(bool val) |
| 354 | 354 | if (ioWrapper.getSslReadWantsWrite()) |
| 355 | 355 | val = true; |
| 356 | 356 | |
| 357 | + // This looks a bit like a race condition, but all calls to this method should be under lock of writeBufMutex, so it should be OK. | |
| 357 | 358 | if (val == this->readyForWriting) |
| 358 | 359 | return; |
| 359 | 360 | |
| 360 | 361 | readyForWriting = val; |
| 362 | + | |
| 361 | 363 | struct epoll_event ev; |
| 362 | 364 | memset(&ev, 0, sizeof (struct epoll_event)); |
| 363 | 365 | ev.data.fd = fd; |
| 364 | - if (readyForReading) | |
| 365 | - ev.events |= EPOLLIN; | |
| 366 | - if (readyForWriting) | |
| 367 | - ev.events |= EPOLLOUT; | |
| 366 | + ev.events = readyForReading*EPOLLIN | readyForWriting*EPOLLOUT; | |
| 368 | 367 | check<std::runtime_error>(epoll_ctl(threadData->epollfd, EPOLL_CTL_MOD, fd, &ev)); |
| 369 | 368 | } |
| 370 | 369 | |
| ... | ... | @@ -378,18 +377,23 @@ void Client::setReadyForReading(bool val) |
| 378 | 377 | if (disconnecting) |
| 379 | 378 | return; |
| 380 | 379 | |
| 380 | + // This looks a bit like a race condition, but all calls to this method are from a threads's event loop, so we should be OK. | |
| 381 | 381 | if (val == this->readyForReading) |
| 382 | 382 | return; |
| 383 | 383 | |
| 384 | 384 | readyForReading = val; |
| 385 | + | |
| 385 | 386 | struct epoll_event ev; |
| 386 | 387 | memset(&ev, 0, sizeof (struct epoll_event)); |
| 387 | 388 | ev.data.fd = fd; |
| 388 | - if (readyForReading) | |
| 389 | - ev.events |= EPOLLIN; | |
| 390 | - if (readyForWriting) | |
| 391 | - ev.events |= EPOLLOUT; | |
| 392 | - check<std::runtime_error>(epoll_ctl(threadData->epollfd, EPOLL_CTL_MOD, fd, &ev)); | |
| 389 | + | |
| 390 | + { | |
| 391 | + // Because setReadyForWriting is always called onder writeBufMutex, this prevents readiness race conditions. | |
| 392 | + std::lock_guard<std::mutex> locker(writeBufMutex); | |
| 393 | + | |
| 394 | + ev.events = readyForReading*EPOLLIN | readyForWriting*EPOLLOUT; | |
| 395 | + check<std::runtime_error>(epoll_ctl(threadData->epollfd, EPOLL_CTL_MOD, fd, &ev)); | |
| 396 | + } | |
| 393 | 397 | } |
| 394 | 398 | |
| 395 | 399 | bool Client::bufferToMqttPackets(std::vector<MqttPacket> &packetQueueIn, std::shared_ptr<Client> &sender) | ... | ... |