0
0
Fork 0
mirror of https://github.com/matrix-construct/construct synced 2025-02-18 01:30:12 +01:00

ircd::net::dns::cache: Fix callback loop assumptions.

ircd::net::dns::resolver: Fix the timeout worker iteration approach.
This commit is contained in:
Jason Volk 2019-09-12 11:03:54 -07:00
parent 5fa545f879
commit 2aa218c366
3 changed files with 40 additions and 37 deletions

View file

@ -418,6 +418,9 @@ ircd::net::dns::cache::hook
decltype(ircd::net::dns::cache::waiting)
ircd::net::dns::cache::waiting;
decltype(ircd::net::dns::cache::mutex)
ircd::net::dns::cache::mutex;
decltype(ircd::net::dns::cache::dock)
ircd::net::dns::cache::dock;
@ -883,42 +886,38 @@ catch(const std::exception &e)
};
}
/// Note complications due to reentrance and other factors:
/// - This function is invoked from several different places on both the
/// timeout and receive contexts, in addition to any evaluator context.
/// - This function calls back to users making DNS queries, and they may
/// conduct another query in their callback frame -- mid-loop in this
/// function.
size_t
ircd::net::dns::cache::call_waiters(const string_view &type,
const string_view &state_key,
const json::array &rrs)
{
const ctx::uninterruptible::nothrow ui;
const scope_notify notify
{
dock, scope_notify::all
};
size_t ret(0), last; do
{
waiter *waiter {nullptr};
const std::lock_guard lock
{
mutex
};
auto it(begin(waiting));
while(it != end(waiting))
{
waiter = std::addressof(*it);
if(call_waiter(type, state_key, rrs, *waiter))
for(last = ret; it != end(waiting); ++it)
if(call_waiter(type, state_key, rrs, *it))
{
it = waiting.erase(it);
++ret;
break;
++it;
}
last = ret;
for(it = begin(waiting); it != end(waiting); ++it)
{
if(std::addressof(*it) != waiter)
continue;
it = waiting.erase(it);
++ret;
break;
}
}
}
while(last > ret);
while(last < ret);
if(ret)
dock.notify_all();
return ret;
}

View file

@ -54,6 +54,7 @@ namespace ircd::net::dns::cache
extern const m::room::id::buf room_id;
extern m::hookfn<m::vm::eval &> hook;
extern std::list<waiter> waiting;
extern ctx::mutex mutex;
extern ctx::dock dock;
}

View file

@ -315,7 +315,6 @@ try
return !tags.empty();
});
ctx::sleep(1500ms);
check_timeouts(milliseconds(timeout));
}
}
@ -333,26 +332,30 @@ catch(const ctx::terminated &)
void
ircd::net::dns::resolver::check_timeouts(const milliseconds &timeout)
{
const std::lock_guard lock
{
mutex
};
const auto cutoff
{
now<steady_point>() - timeout
};
auto it(begin(tags));
while(it != end(tags))
std::unique_lock lock
{
mutex
};
auto it(begin(tags));
for(; it != end(tags); ++it)
{
const auto &id(it->first);
auto &tag(it->second);
const auto &id(it->first);
if(check_timeout(id, tag, cutoff))
it = remove(tag, it);
else
++it;
{
it = tags.erase(it);
return;
}
}
lock.unlock();
ctx::sleep(1800ms);
}
bool