Commit b55a98946f9837e22e8a2cdad22147f1c5ab822e

Authored by Wiebe Cazemier
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)
... ...