Commit 536086dc authored by Dan Melnic's avatar Dan Melnic Committed by Facebook GitHub Bot

Delay registration of the timer and signal fds until running the loop first time

Summary:
Delay registration of the timer and signal fds until running the loop first time
On some Linux kernel versions, io_uring will remove any fd registrations on thread exit. So creating the backend in a thread that exits later will cause us not to receive timer and signal fd events.

Reviewed By: kevin-vigor

Differential Revision: D26200805

fbshipit-source-id: dc3025964deb3cf87bf3e5a27141abcdb8698caf
parent 20549953
...@@ -448,11 +448,7 @@ IoUringBackend::IoUringBackend(Options options) ...@@ -448,11 +448,7 @@ IoUringBackend::IoUringBackend(Options options)
fdRegistry_.init(); fdRegistry_.init();
} }
// add the timer fd // delay adding the timer and signal fds until running the loop first time
if (!addTimerFd() || !addSignalFds()) {
cleanup();
throw NotAvailable("io_uring_submit error");
}
} }
IoUringBackend::~IoUringBackend() { IoUringBackend::~IoUringBackend() {
...@@ -828,6 +824,14 @@ size_t IoUringBackend::processActiveEvents() { ...@@ -828,6 +824,14 @@ size_t IoUringBackend::processActiveEvents() {
} }
int IoUringBackend::eb_event_base_loop(int flags) { int IoUringBackend::eb_event_base_loop(int flags) {
if (FOLLY_UNLIKELY(registerDefaultFds_)) {
registerDefaultFds_ = false;
if (!addTimerFd() || !addSignalFds()) {
cleanup();
throw NotAvailable("io_uring_submit error");
}
}
// schedule the timers // schedule the timers
bool done = false; bool done = false;
auto waitForEvents = (flags & EVLOOP_NONBLOCK) ? WaitForEventsMode::DONT_WAIT auto waitForEvents = (flags & EVLOOP_NONBLOCK) ? WaitForEventsMode::DONT_WAIT
......
...@@ -796,6 +796,8 @@ class IoUringBackend : public EventBaseBackendBase { ...@@ -796,6 +796,8 @@ class IoUringBackend : public EventBaseBackendBase {
// poll callback to be invoked if POLL_CQ flag is set // poll callback to be invoked if POLL_CQ flag is set
// every time we poll for a CQE // every time we poll for a CQE
CQPollLoopCallback cqPollLoopCallback_; CQPollLoopCallback cqPollLoopCallback_;
bool registerDefaultFds_{true};
}; };
using PollIoBackend = IoUringBackend; using PollIoBackend = IoUringBackend;
......
...@@ -554,10 +554,10 @@ TEST(IoUringBackend, RegisteredFds) { ...@@ -554,10 +554,10 @@ TEST(IoUringBackend, RegisteredFds) {
CHECK(!record); CHECK(!record);
std::vector<folly::IoUringBackend::FdRegistrationRecord*> records; std::vector<folly::IoUringBackend::FdRegistrationRecord*> records;
// we use kBackendCapacity -1 since we can have the timerFd // we use kBackendCapacity since the timerFd
// already using one fd // allocates it only on the first loop
records.reserve(kBackendCapacity - 1); records.reserve(kBackendCapacity);
for (size_t i = 0; i < kBackendCapacity - 1; i++) { for (size_t i = 0; i < kBackendCapacity; i++) {
record = backendReg->registerFd(eventFd); record = backendReg->registerFd(eventFd);
CHECK(record); CHECK(record);
records.emplace_back(record); records.emplace_back(record);
......
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