Commit 6e142c0d authored by Yedidya Feldblum's avatar Yedidya Feldblum Committed by Facebook Github Bot

Fix unsynchronized accesses in IOThreadPoolExecutor::getEventBase

Summary:
[Folly] Fix unsynchronized accesses in `IOThreadPoolExecutor::getEventBase`.

`getEventBase` may be invoked concurrently from two threads - RMWs to `nextThread_` must be synchronized with each other.

`getEventBase` may be invoked concurrently with `setNumThreads` - the former's reads of `threadList_.vec_` must be synchronized with the latter's writes to it.

Reviewed By: kennyyu

Differential Revision: D6206916

fbshipit-source-id: 8bfae158effb5896ab478d0c20310293b037c892
parent 9216d96a
...@@ -119,11 +119,12 @@ IOThreadPoolExecutor::pickThread() { ...@@ -119,11 +119,12 @@ IOThreadPoolExecutor::pickThread() {
if (n == 0) { if (n == 0) {
return me; return me;
} }
auto thread = ths[nextThread_++ % n]; auto thread = ths[nextThread_.fetch_add(1, std::memory_order_relaxed) % n];
return std::static_pointer_cast<IOThread>(thread); return std::static_pointer_cast<IOThread>(thread);
} }
EventBase* IOThreadPoolExecutor::getEventBase() { EventBase* IOThreadPoolExecutor::getEventBase() {
RWSpinLock::ReadHolder r{&threadListLock_};
return pickThread()->eventBase; return pickThread()->eventBase;
} }
......
...@@ -16,6 +16,8 @@ ...@@ -16,6 +16,8 @@
#pragma once #pragma once
#include <atomic>
#include <folly/executors/IOExecutor.h> #include <folly/executors/IOExecutor.h>
#include <folly/executors/ThreadPoolExecutor.h> #include <folly/executors/ThreadPoolExecutor.h>
#include <folly/io/async/EventBaseManager.h> #include <folly/io/async/EventBaseManager.h>
...@@ -86,7 +88,7 @@ class IOThreadPoolExecutor : public ThreadPoolExecutor, public IOExecutor { ...@@ -86,7 +88,7 @@ class IOThreadPoolExecutor : public ThreadPoolExecutor, public IOExecutor {
void stopThreads(size_t n) override; void stopThreads(size_t n) override;
uint64_t getPendingTaskCountImpl(const RWSpinLock::ReadHolder&) override; uint64_t getPendingTaskCountImpl(const RWSpinLock::ReadHolder&) override;
size_t nextThread_; std::atomic<size_t> nextThread_;
folly::ThreadLocal<std::shared_ptr<IOThread>> thisThread_; folly::ThreadLocal<std::shared_ptr<IOThread>> thisThread_;
folly::EventBaseManager* eventBaseManager_; folly::EventBaseManager* eventBaseManager_;
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment