mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-30 08:12:05 +00:00
Backed out changeset 10479ec2f64e (bug 1853497) for causing process crashes in libresolv.so.
This commit is contained in:
parent
bb32350be3
commit
250455b0be
@ -10,13 +10,13 @@
|
||||
# include <arpa/inet.h>
|
||||
# include <arpa/nameser.h>
|
||||
# include <resolv.h>
|
||||
# define RES_RETRY_ON_FAILURE
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <ctime>
|
||||
#include "nsHostResolver.h"
|
||||
#include "nsError.h"
|
||||
#include "nsIOService.h"
|
||||
#include "nsISupports.h"
|
||||
#include "nsISupportsUtils.h"
|
||||
#include "nsIThreadManager.h"
|
||||
@ -98,54 +98,45 @@ LazyLogModule gHostResolverLog("nsHostResolver");
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#if defined(HAVE_RES_NINIT)
|
||||
#if defined(RES_RETRY_ON_FAILURE)
|
||||
|
||||
// The nsResState class manages the res state.
|
||||
// This class ensures the resolver state is reset based on network change events
|
||||
// to maintain correct DNS resolutions.
|
||||
class MOZ_STACK_CLASS nsResState {
|
||||
// this class represents the resolver state for a given thread. if we
|
||||
// encounter a lookup failure, then we can invoke the Reset method on an
|
||||
// instance of this class to reset the resolver (in case /etc/resolv.conf
|
||||
// for example changed). this is mainly an issue on GNU systems since glibc
|
||||
// only reads in /etc/resolv.conf once per thread. it may be an issue on
|
||||
// other systems as well.
|
||||
|
||||
class nsResState {
|
||||
public:
|
||||
// Set mLastReset to now, which should be larger than last network change
|
||||
// time, so we won't reset when the thread just started.
|
||||
nsResState() : mLastReset(PR_IntervalNow()) {}
|
||||
nsResState()
|
||||
// initialize mLastReset to the time when this object
|
||||
// is created. this means that a reset will not occur
|
||||
// if a thread is too young. the alternative would be
|
||||
// to initialize this to the beginning of time, so that
|
||||
// the first failure would cause a reset, but since the
|
||||
// thread would have just started up, it likely would
|
||||
// already have current /etc/resolv.conf info.
|
||||
: mLastReset(PR_IntervalNow()) {}
|
||||
|
||||
~nsResState() {
|
||||
if (_res.options & RES_INIT) {
|
||||
res_nclose(&_res);
|
||||
}
|
||||
}
|
||||
|
||||
void Init() {
|
||||
if (!(_res.options & RES_INIT)) {
|
||||
auto result = res_ninit(&_res);
|
||||
LOG(("nsResState > 'res_ninit' returned %d ", result));
|
||||
}
|
||||
}
|
||||
|
||||
void MaybeReset() {
|
||||
if (mLastReset > gIOService->LastNetworkLinkChange()) {
|
||||
return;
|
||||
}
|
||||
|
||||
PRIntervalTime now = PR_IntervalNow();
|
||||
bool Reset() {
|
||||
// reset no more than once per second
|
||||
if (PR_IntervalToSeconds(now - mLastReset) < 1) {
|
||||
return;
|
||||
if (PR_IntervalToSeconds(PR_IntervalNow() - mLastReset) < 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (_res.options & RES_INIT) {
|
||||
res_nclose(&_res);
|
||||
}
|
||||
mLastReset = PR_IntervalNow();
|
||||
auto result = res_ninit(&_res);
|
||||
|
||||
mLastReset = now;
|
||||
Init();
|
||||
LOG(("nsResState::Reset() > 'res_ninit' returned %d", result));
|
||||
return (result == 0);
|
||||
}
|
||||
|
||||
private:
|
||||
PRIntervalTime mLastReset;
|
||||
};
|
||||
|
||||
#endif // HAVE_RES_NINIT
|
||||
#endif // RES_RETRY_ON_FAILURE
|
||||
|
||||
class DnsThreadListener final : public nsIThreadPoolListener {
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
@ -233,6 +224,19 @@ nsresult nsHostResolver::Init() MOZ_NO_THREAD_SAFETY_ANALYSIS {
|
||||
"Could not register DNS pref callback.");
|
||||
}
|
||||
|
||||
#if defined(HAVE_RES_NINIT)
|
||||
// We want to make sure the system is using the correct resolver settings,
|
||||
// so we force it to reload those settings whenever we startup a subsequent
|
||||
// nsHostResolver instance. We assume that there is no reason to do this
|
||||
// for the first nsHostResolver instance since that is usually created
|
||||
// during application startup.
|
||||
static int initCount = 0;
|
||||
if (initCount++ > 0) {
|
||||
auto result = res_ninit(&_res);
|
||||
LOG(("nsHostResolver::Init > 'res_ninit' returned %d", result));
|
||||
}
|
||||
#endif
|
||||
|
||||
// We can configure the threadpool to keep threads alive for a while after
|
||||
// the last ThreadFunc task has been executed.
|
||||
int32_t poolTimeoutSecs = Preferences::GetInt(kPrefThreadIdleTime, 60);
|
||||
@ -1841,9 +1845,8 @@ size_t nsHostResolver::SizeOfIncludingThis(MallocSizeOf mallocSizeOf) const {
|
||||
void nsHostResolver::ThreadFunc() {
|
||||
LOG(("DNS lookup thread - starting execution.\n"));
|
||||
|
||||
#if defined(HAVE_RES_NINIT)
|
||||
#if defined(RES_RETRY_ON_FAILURE)
|
||||
nsResState rs;
|
||||
rs.Init();
|
||||
#endif
|
||||
RefPtr<nsHostRecord> rec;
|
||||
RefPtr<AddrInfo> ai;
|
||||
@ -1884,11 +1887,14 @@ void nsHostResolver::ThreadFunc() {
|
||||
continue;
|
||||
}
|
||||
|
||||
#if defined(HAVE_RES_NINIT)
|
||||
rs.MaybeReset();
|
||||
#endif
|
||||
nsresult status =
|
||||
GetAddrInfo(rec->host, rec->af, rec->flags, getter_AddRefs(ai), getTtl);
|
||||
#if defined(RES_RETRY_ON_FAILURE)
|
||||
if (NS_FAILED(status) && rs.Reset()) {
|
||||
status = GetAddrInfo(rec->host, rec->af, rec->flags, getter_AddRefs(ai),
|
||||
getTtl);
|
||||
}
|
||||
#endif
|
||||
|
||||
mozilla::glean::networking::dns_native_count
|
||||
.EnumGet(rec->pb ? glean::networking::DnsNativeCountLabel::ePrivate
|
||||
|
Loading…
Reference in New Issue
Block a user