RequestServer: Pre-resolve preconnect handles via our DNS resolver
handle_connect_state (used by <link rel=preconnect>) attached easy handles to the multi without setting CURLOPT_RESOLVE, so libcurl spawned its own threaded resolver for them. When the system stub resolver was slow, the thread got stuck and the next ~Request pthread_join'd it on the main thread for many seconds. Route Connect-mode requests through the same DNS + CURLOPT_RESOLVE path that Fetch uses, so libcurl never spawns the thread.
This commit is contained in:
parent
6f4096a4ca
commit
03d1b37354
2 changed files with 16 additions and 10 deletions
|
|
@ -386,16 +386,8 @@ NonnullOwnPtr<Request> Request::connect(
|
|||
CacheLevel cache_level)
|
||||
{
|
||||
auto request = adopt_own(*new Request { request_id, client, curl_multi, resolver, move(url) });
|
||||
|
||||
switch (cache_level) {
|
||||
case CacheLevel::ResolveOnly:
|
||||
request->transition_to_state(State::DNSLookup);
|
||||
break;
|
||||
case CacheLevel::CreateConnection:
|
||||
request->transition_to_state(State::Connect);
|
||||
break;
|
||||
}
|
||||
|
||||
request->m_connect_cache_level = cache_level;
|
||||
request->transition_to_state(State::DNSLookup);
|
||||
return request;
|
||||
}
|
||||
|
||||
|
|
@ -800,6 +792,9 @@ void Request::handle_dns_lookup_state()
|
|||
} else if (first_is_one_of(self.m_type, RequestType::Fetch, RequestType::BackgroundRevalidation)) {
|
||||
self.m_dns_result = move(dns_result);
|
||||
self.transition_to_state(State::RetrieveCookie);
|
||||
} else if (self.m_type == RequestType::Connect && self.m_connect_cache_level == CacheLevel::CreateConnection) {
|
||||
self.m_dns_result = move(dns_result);
|
||||
self.transition_to_state(State::Connect);
|
||||
} else {
|
||||
self.transition_to_state(State::Complete);
|
||||
}
|
||||
|
|
@ -844,6 +839,16 @@ void Request::handle_connect_state()
|
|||
set_option(CURLOPT_CONNECTTIMEOUT, s_connect_timeout_seconds);
|
||||
set_option(CURLOPT_CONNECT_ONLY, 1L);
|
||||
|
||||
// Pre-populate the multi's hostcache so libcurl skips its threaded resolver entirely.
|
||||
VERIFY(m_dns_result);
|
||||
auto formatted_address = build_curl_resolve_list(*m_dns_result, m_url.serialized_host(), m_url.port_or_default());
|
||||
if (curl_slist* resolve_list = curl_slist_append(nullptr, formatted_address.characters())) {
|
||||
set_option(CURLOPT_RESOLVE, resolve_list);
|
||||
m_curl_string_lists.append(resolve_list);
|
||||
} else {
|
||||
VERIFY_NOT_REACHED();
|
||||
}
|
||||
|
||||
mark_lifecycle_event(this, &WireStats::curl_added_at);
|
||||
auto result = curl_multi_add_handle(m_curl_multi_handle, m_curl_easy_handle);
|
||||
VERIFY(result == CURLM_OK);
|
||||
|
|
|
|||
|
|
@ -189,6 +189,7 @@ private:
|
|||
|
||||
NonnullRefPtr<Resolver> m_resolver;
|
||||
RefPtr<DNS::LookupResult const> m_dns_result;
|
||||
CacheLevel m_connect_cache_level { CacheLevel::ResolveOnly };
|
||||
|
||||
URL::URL m_url;
|
||||
ByteString m_method;
|
||||
|
|
|
|||
Loading…
Reference in a new issue