@@ -265,36 +265,46 @@ class DefaultResolver : public Resolver {
265265 struct IPAddrList : public intrusive_list <IPAddrNode>, spinlock {
266266 ~IPAddrList () { delete_all (); }
267267 };
268+ struct ResolveCtx {
269+ std::string host;
270+ Delegate<bool , IPAddr> filter;
271+ spinlock lock;
272+ IPAddrList *addrs;
273+ photon::semaphore sem;
274+ };
268275 IPAddr do_resolve (std::string_view host, Delegate<bool , IPAddr> filter) {
269276 auto ctr = [&]() -> IPAddrList* {
270- auto addrs = new IPAddrList ();
271- photon::semaphore sem;
272- std::thread ([&]() {
273- auto now = std::chrono::steady_clock::now ();
274- IPAddrList ret;
277+ std::unique_ptr<IPAddrList> addrs (new IPAddrList ());
278+ auto ctx = std::make_shared<ResolveCtx>();
279+ ctx->addrs = addrs.get ();
280+ ctx->host = std::string (host);
281+ ctx->filter = filter;
282+ std::thread ([ctx]() {
275283 auto cb = [&](IPAddr addr) -> int {
276- if (filter && !filter.fire (addr))
277- return 0 ;
278- ret.push_back (new IPAddrNode (addr));
284+ SCOPED_LOCK (ctx->lock );
285+ if (ctx->filter && !ctx->filter .fire (addr)) return 0 ;
286+ if (ctx->addrs ) {
287+ ctx->addrs ->push_back (new IPAddrNode (addr));
288+ }
279289 return 0 ;
280290 };
281- _gethostbyname (host, cb);
282- auto time_elapsed = std::chrono::duration_cast<std::chrono::microseconds>(
283- std::chrono::steady_clock::now () - now).count ();
284- if ((uint64_t )time_elapsed <= resolve_timeout_) {
285- addrs->push_back (std::move (ret));
286- sem.signal (1 );
287- } else {
288- LOG_ERROR (" resolve timeout" );
289- while (!ret.empty ())
290- delete ret.pop_front ();
291- }
291+ _gethostbyname (ctx->host , cb);
292+ ctx->sem .signal (1 );
292293 }).detach ();
293- sem.wait (1 , resolve_timeout_);
294- return addrs;
294+ ctx->sem .wait (1 , resolve_timeout_);
295+ SCOPED_LOCK (ctx->lock );
296+ ctx->addrs = nullptr ;
297+ ctx->filter = {};
298+ if (addrs->empty ()) {
299+ return nullptr ;
300+ }
301+ return addrs.release ();
295302 };
296- auto ips = dnscache_.borrow (host, ctr);
297- if (ips->empty ()) LOG_ERRNO_RETURN (0 , IPAddr (), " Domain resolution for '`' failed" , host);
303+ auto ips = dnscache_.borrow (host, ctr, 1UL * 1000 );
304+ if (!ips || ips->empty ()) {
305+ ips.recycle (true );
306+ LOG_ERRNO_RETURN (0 , IPAddr (), " Domain resolution for '`' failed" , host);
307+ }
298308 SCOPED_LOCK (*ips);
299309 return ips->round_robin_next ()->addr ;
300310 }
0 commit comments