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:
parent
5fa545f879
commit
2aa218c366
3 changed files with 40 additions and 37 deletions
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Reference in a new issue