Commit d4af6bb8 authored by Akrama Baig Mirza's avatar Akrama Baig Mirza Committed by Facebook GitHub Bot

Add ThreadIdCollector to IOThreadPoolDeadlockDetectorObserver

Summary:
Add an implementation of `WorkerProvider` to `IOThreadPoolDeadlockDetectorObserver`.

- On thread start, the observer creates a `TaskStallDetector` and provides it a `ThreadIdCollector` containing the TID of the thread that started
- The thread will be blocked from exiting until any existing `WorkerProvider::KeepAlive`s are destroyed

Differential Revision: D31963855

fbshipit-source-id: cd749d76a433684a8280d95a4dbff441e32bfda9
parent ddcb646b
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#pragma once #pragma once
#include <folly/Executor.h> #include <folly/Executor.h>
#include <folly/executors/QueueObserver.h>
namespace folly { namespace folly {
class DeadlockDetector { class DeadlockDetector {
...@@ -28,7 +29,9 @@ class DeadlockDetectorFactory { ...@@ -28,7 +29,9 @@ class DeadlockDetectorFactory {
public: public:
virtual ~DeadlockDetectorFactory() {} virtual ~DeadlockDetectorFactory() {}
virtual std::unique_ptr<DeadlockDetector> create( virtual std::unique_ptr<DeadlockDetector> create(
Executor* executor, const std::string& name) = 0; Executor* executor,
const std::string& name,
std::unique_ptr<WorkerProvider> threadIdCollector) = 0;
static DeadlockDetectorFactory* instance(); static DeadlockDetectorFactory* instance();
}; };
......
...@@ -21,6 +21,35 @@ ...@@ -21,6 +21,35 @@
namespace folly { namespace folly {
namespace {
class ThreadIdCollector : public WorkerProvider {
public:
ThreadIdCollector(pid_t tid, std::mutex& eventBaseShutdownMutex)
: tid_(tid), eventBaseShutdownMutex_(eventBaseShutdownMutex) {}
IdsWithKeepAlive collectThreadIds() override final {
std::unique_lock<std::mutex> guard(eventBaseShutdownMutex_);
return {
std::make_unique<WorkerKeepAlive>(std::move(guard)),
std::vector<pid_t>{tid_}};
}
private:
class WorkerKeepAlive : public WorkerProvider::KeepAlive {
public:
explicit WorkerKeepAlive(std::unique_lock<std::mutex> lock)
: lock_(std::move(lock)) {}
~WorkerKeepAlive() override {}
private:
std::unique_lock<std::mutex> lock_;
};
pid_t tid_;
std::mutex& eventBaseShutdownMutex_;
};
} // namespace
IOThreadPoolDeadlockDetectorObserver::IOThreadPoolDeadlockDetectorObserver( IOThreadPoolDeadlockDetectorObserver::IOThreadPoolDeadlockDetectorObserver(
DeadlockDetectorFactory* deadlockDetectorFactory, const std::string& name) DeadlockDetectorFactory* deadlockDetectorFactory, const std::string& name)
: name_(name), deadlockDetectorFactory_(deadlockDetectorFactory) {} : name_(name), deadlockDetectorFactory_(deadlockDetectorFactory) {}
...@@ -32,13 +61,19 @@ void IOThreadPoolDeadlockDetectorObserver::threadStarted( ...@@ -32,13 +61,19 @@ void IOThreadPoolDeadlockDetectorObserver::threadStarted(
} }
auto eventBase = folly::IOThreadPoolExecutor::getEventBase(h); auto eventBase = folly::IOThreadPoolExecutor::getEventBase(h);
auto eventBaseShutdownMutex =
folly::IOThreadPoolExecutor::getEventBaseShutdownMutex(h);
// This Observer only works with IOThreadPoolExecutor class. // This Observer only works with IOThreadPoolExecutor class.
CHECK_NOTNULL(eventBase); CHECK_NOTNULL(eventBase);
CHECK_NOTNULL(eventBaseShutdownMutex);
eventBase->runInEventBaseThread([=] { eventBase->runInEventBaseThread([=] {
auto thid = folly::to<std::string>(folly::getOSThreadID()); auto tid = folly::getOSThreadID();
auto name = name_ + ":" + thid; auto name = name_ + ":" + folly::to<std::string>(tid);
detectors_.wlock()->insert_or_assign( auto deadlockDetector = deadlockDetectorFactory_->create(
h, deadlockDetectorFactory_->create(eventBase, name)); eventBase,
name,
std::make_unique<ThreadIdCollector>(tid, *eventBaseShutdownMutex));
detectors_.wlock()->insert_or_assign(h, std::move(deadlockDetector));
}); });
} }
......
...@@ -183,6 +183,17 @@ EventBase* IOThreadPoolExecutor::getEventBase( ...@@ -183,6 +183,17 @@ EventBase* IOThreadPoolExecutor::getEventBase(
return nullptr; return nullptr;
} }
std::mutex* IOThreadPoolExecutor::getEventBaseShutdownMutex(
ThreadPoolExecutor::ThreadHandle* h) {
auto thread = dynamic_cast<IOThread*>(h);
if (thread) {
return &thread->eventBaseShutdownMutex_;
}
return nullptr;
}
EventBaseManager* IOThreadPoolExecutor::getEventBaseManager() { EventBaseManager* IOThreadPoolExecutor::getEventBaseManager() {
return eventBaseManager_; return eventBaseManager_;
} }
......
...@@ -83,6 +83,9 @@ class IOThreadPoolExecutor : public ThreadPoolExecutor, public IOExecutor { ...@@ -83,6 +83,9 @@ class IOThreadPoolExecutor : public ThreadPoolExecutor, public IOExecutor {
static folly::EventBase* getEventBase(ThreadPoolExecutor::ThreadHandle*); static folly::EventBase* getEventBase(ThreadPoolExecutor::ThreadHandle*);
static std::mutex* getEventBaseShutdownMutex(
ThreadPoolExecutor::ThreadHandle*);
folly::EventBaseManager* getEventBaseManager(); folly::EventBaseManager* getEventBaseManager();
private: private:
......
...@@ -40,11 +40,18 @@ class DeadlockDetectorMock : public DeadlockDetector { ...@@ -40,11 +40,18 @@ class DeadlockDetectorMock : public DeadlockDetector {
class DeadlockDetectorFactoryMock : public DeadlockDetectorFactory { class DeadlockDetectorFactoryMock : public DeadlockDetectorFactory {
public: public:
std::unique_ptr<DeadlockDetector> create( std::unique_ptr<DeadlockDetector> create(
folly::Executor* executor, const std::string& name) override { folly::Executor* executor,
const std::string& name,
std::unique_ptr<WorkerProvider> tidCollector) override {
EXPECT_TRUE(executor != nullptr); EXPECT_TRUE(executor != nullptr);
std::string expectedName = auto tid = folly::getOSThreadID();
fmt::format("TestPool:{}", folly::getOSThreadID()); std::string expectedName = fmt::format("TestPool:{}", tid);
EXPECT_EQ(expectedName, name); EXPECT_EQ(expectedName, name);
{
auto tids = tidCollector->collectThreadIds();
EXPECT_EQ(1, tids.threadIds.size());
EXPECT_EQ(tid, tids.threadIds[0]);
}
name_ = name; name_ = name;
auto retval = std::make_unique<DeadlockDetectorMock>(counter_); auto retval = std::make_unique<DeadlockDetectorMock>(counter_);
baton.post(); baton.post();
......
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