зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1207753 - netwerk/dns thread-safety annotations r=necko-reviewers,dragana
Differential Revision: https://phabricator.services.mozilla.com/D130580
This commit is contained in:
Родитель
8da8a144a5
Коммит
39e3372695
|
@ -3055,7 +3055,6 @@ void MediaFormatReader::NotifyDataArrived() {
|
|||
}
|
||||
|
||||
void MediaFormatReader::UpdateMediaEngineId(uint64_t aMediaEngineId) {
|
||||
MOZ_ASSERT(OnTaskQueue());
|
||||
LOG("Update external media engine Id %" PRIu64, aMediaEngineId);
|
||||
mMediaEngineId = Some(aMediaEngineId);
|
||||
}
|
||||
|
|
|
@ -58,18 +58,18 @@ class ODoHService : public nsIDNSListener,
|
|||
nsresult UpdateODoHConfigFromHTTPSRR();
|
||||
nsresult UpdateODoHConfigFromURI();
|
||||
|
||||
mozilla::Mutex mLock MOZ_UNANNOTATED;
|
||||
mozilla::Mutex mLock;
|
||||
Atomic<bool, Relaxed> mQueryODoHConfigInProgress;
|
||||
nsCString mODoHProxyURI;
|
||||
nsCString mODoHTargetHost;
|
||||
nsCString mODoHTargetPath;
|
||||
nsCString mODoHRequestURI;
|
||||
nsCString mODoHConfigsUri;
|
||||
Maybe<nsTArray<ObliviousDoHConfig>> mODoHConfigs;
|
||||
nsTArray<RefPtr<ODoH>> mPendingRequests;
|
||||
nsCString mODoHProxyURI GUARDED_BY(mLock);
|
||||
nsCString mODoHTargetHost GUARDED_BY(mLock);
|
||||
nsCString mODoHTargetPath GUARDED_BY(mLock);
|
||||
nsCString mODoHRequestURI GUARDED_BY(mLock);
|
||||
nsCString mODoHConfigsUri GUARDED_BY(mLock);
|
||||
Maybe<nsTArray<ObliviousDoHConfig>> mODoHConfigs GUARDED_BY(mLock);
|
||||
nsTArray<RefPtr<ODoH>> mPendingRequests GUARDED_BY(mLock);
|
||||
// This timer is always touched on main thread to avoid race conditions.
|
||||
nsCOMPtr<nsITimer> mTTLTimer;
|
||||
nsCOMPtr<nsIStreamLoader> mLoader;
|
||||
nsCOMPtr<nsIStreamLoader> mLoader GUARDED_BY(mLock);
|
||||
};
|
||||
|
||||
extern ODoHService* gODoHService;
|
||||
|
|
|
@ -65,7 +65,9 @@ NS_IMPL_RELEASE_USING_AGGREGATOR(TRRService::ConfirmationContext,
|
|||
NS_IMPL_QUERY_INTERFACE(TRRService::ConfirmationContext, nsITimerCallback,
|
||||
nsINamed)
|
||||
|
||||
TRRService::TRRService() { MOZ_ASSERT(NS_IsMainThread(), "wrong thread"); }
|
||||
TRRService::TRRService() : mLock("TRRService", this) {
|
||||
MOZ_ASSERT(NS_IsMainThread(), "wrong thread");
|
||||
}
|
||||
|
||||
// static
|
||||
TRRService* TRRService::Get() { return sTRRServicePtr; }
|
||||
|
@ -262,7 +264,7 @@ bool TRRService::MaybeSetPrivateURI(const nsACString& aURI) {
|
|||
|
||||
ProcessURITemplate(newURI);
|
||||
{
|
||||
MutexAutoLock lock(mLock);
|
||||
MutexSingleWriterAutoLock lock(mLock);
|
||||
if (mPrivateURI.Equals(newURI)) {
|
||||
return false;
|
||||
}
|
||||
|
@ -344,16 +346,16 @@ nsresult TRRService::ReadPrefs(const char* name) {
|
|||
OnTRRURIChange();
|
||||
}
|
||||
if (!name || !strcmp(name, TRR_PREF("credentials"))) {
|
||||
MutexAutoLock lock(mLock);
|
||||
MutexSingleWriterAutoLock lock(mLock);
|
||||
Preferences::GetCString(TRR_PREF("credentials"), mPrivateCred);
|
||||
}
|
||||
if (!name || !strcmp(name, TRR_PREF("confirmationNS"))) {
|
||||
MutexAutoLock lock(mLock);
|
||||
MutexSingleWriterAutoLock lock(mLock);
|
||||
Preferences::GetCString(TRR_PREF("confirmationNS"), mConfirmationNS);
|
||||
LOG(("confirmationNS = %s", mConfirmationNS.get()));
|
||||
}
|
||||
if (!name || !strcmp(name, TRR_PREF("bootstrapAddr"))) {
|
||||
MutexAutoLock lock(mLock);
|
||||
MutexSingleWriterAutoLock lock(mLock);
|
||||
Preferences::GetCString(TRR_PREF("bootstrapAddr"), mBootstrapAddr);
|
||||
clearEntireCache = true;
|
||||
}
|
||||
|
@ -365,11 +367,12 @@ nsresult TRRService::ReadPrefs(const char* name) {
|
|||
}
|
||||
if (!name || !strcmp(name, TRR_PREF("excluded-domains")) ||
|
||||
!strcmp(name, TRR_PREF("builtin-excluded-domains"))) {
|
||||
MutexAutoLock lock(mLock);
|
||||
MutexSingleWriterAutoLock lock(mLock);
|
||||
mExcludedDomains.Clear();
|
||||
|
||||
auto parseExcludedDomains = [this](const char* aPrefName) {
|
||||
nsAutoCString excludedDomains;
|
||||
mLock.AssertCurrentThreadOwns();
|
||||
Preferences::GetCString(aPrefName, excludedDomains);
|
||||
if (excludedDomains.IsEmpty()) {
|
||||
return;
|
||||
|
@ -412,7 +415,7 @@ void TRRService::ClearEntireCache() {
|
|||
}
|
||||
|
||||
void TRRService::AddEtcHosts(const nsTArray<nsCString>& aArray) {
|
||||
MutexAutoLock lock(mLock);
|
||||
MutexSingleWriterAutoLock lock(mLock);
|
||||
for (const auto& item : aArray) {
|
||||
LOG(("Adding %s from /etc/hosts to excluded domains", item.get()));
|
||||
mEtcHostsDomains.Insert(item);
|
||||
|
@ -434,12 +437,12 @@ void TRRService::ReadEtcHostsFile() {
|
|||
}
|
||||
|
||||
void TRRService::GetURI(nsACString& result) {
|
||||
MutexAutoLock lock(mLock);
|
||||
MutexSingleWriterAutoLock lock(mLock);
|
||||
result = mPrivateURI;
|
||||
}
|
||||
|
||||
nsresult TRRService::GetCredentials(nsCString& result) {
|
||||
MutexAutoLock lock(mLock);
|
||||
MutexSingleWriterAutoLock lock(mLock);
|
||||
result = mPrivateCred;
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -497,7 +500,7 @@ already_AddRefed<nsIThread> TRRService::MainThreadOrTRRThread(bool aWithLock) {
|
|||
}
|
||||
|
||||
already_AddRefed<nsIThread> TRRService::TRRThread() {
|
||||
MutexAutoLock lock(mLock);
|
||||
MutexSingleWriterAutoLock lock(mLock);
|
||||
return TRRThread_locked();
|
||||
}
|
||||
|
||||
|
@ -509,7 +512,7 @@ already_AddRefed<nsIThread> TRRService::TRRThread_locked() {
|
|||
bool TRRService::IsOnTRRThread() {
|
||||
nsCOMPtr<nsIThread> thread;
|
||||
{
|
||||
MutexAutoLock lock(mLock);
|
||||
MutexSingleWriterAutoLock lock(mLock);
|
||||
thread = sTRRBackgroundThread;
|
||||
}
|
||||
if (!thread) {
|
||||
|
@ -530,7 +533,7 @@ TRRService::Observe(nsISupports* aSubject, const char* aTopic,
|
|||
mConfirmationTriggered = false;
|
||||
ReadPrefs(NS_ConvertUTF16toUTF8(aData).get());
|
||||
{
|
||||
MutexAutoLock lock(mLock);
|
||||
MutexSingleWriterAutoLock lock(mLock);
|
||||
mConfirmation.RecordEvent("pref-change", lock);
|
||||
}
|
||||
|
||||
|
@ -582,7 +585,7 @@ TRRService::Observe(nsISupports* aSubject, const char* aTopic,
|
|||
if (!strcmp(aTopic, NS_NETWORK_LINK_TOPIC)) {
|
||||
if (NS_ConvertUTF16toUTF8(aData).EqualsLiteral(
|
||||
NS_NETWORK_LINK_DATA_DOWN)) {
|
||||
MutexAutoLock lock(mLock);
|
||||
MutexSingleWriterAutoLock lock(mLock);
|
||||
mConfirmation.RecordEvent("network-change", lock);
|
||||
}
|
||||
|
||||
|
@ -600,7 +603,7 @@ TRRService::Observe(nsISupports* aSubject, const char* aTopic,
|
|||
// If a confirmation is still in progress we record the event.
|
||||
// Since there should be no more confirmations after this, the shutdown
|
||||
// reason would not really be recorded in telemetry.
|
||||
MutexAutoLock lock(mLock);
|
||||
MutexSingleWriterAutoLock lock(mLock);
|
||||
mConfirmation.RecordEvent("shutdown", lock);
|
||||
|
||||
if (sTRRBackgroundThread) {
|
||||
|
@ -619,7 +622,7 @@ void TRRService::RebuildSuffixList(nsTArray<nsCString>&& aSuffixList) {
|
|||
return;
|
||||
}
|
||||
|
||||
MutexAutoLock lock(mLock);
|
||||
MutexSingleWriterAutoLock lock(mLock);
|
||||
mDNSSuffixDomains.Clear();
|
||||
for (const auto& item : aSuffixList) {
|
||||
LOG(("TRRService adding %s to suffix list", item.get()));
|
||||
|
@ -646,18 +649,20 @@ void TRRService::ConfirmationContext::SetState(
|
|||
}
|
||||
|
||||
bool TRRService::ConfirmationContext::HandleEvent(ConfirmationEvent aEvent) {
|
||||
MutexAutoLock lock(OwningObject()->mLock);
|
||||
MutexSingleWriterAutoLock lock(OwningObject()->mLock);
|
||||
return HandleEvent(aEvent, lock);
|
||||
}
|
||||
|
||||
bool TRRService::ConfirmationContext::HandleEvent(ConfirmationEvent aEvent,
|
||||
const MutexAutoLock&) {
|
||||
// We're protected by service->mLock
|
||||
bool TRRService::ConfirmationContext::HandleEvent(
|
||||
ConfirmationEvent aEvent, const MutexSingleWriterAutoLock&) {
|
||||
auto prevAddr = TaskAddr();
|
||||
TRRService* service = OwningObject();
|
||||
service->mLock.AssertCurrentThreadOwns();
|
||||
nsIDNSService::ResolverMode mode = service->Mode();
|
||||
|
||||
auto resetConfirmation = [&]() {
|
||||
service->mLock.AssertCurrentThreadOwns();
|
||||
mTask = nullptr;
|
||||
nsCOMPtr<nsITimer> timer = std::move(mTimer);
|
||||
if (timer) {
|
||||
|
@ -692,6 +697,7 @@ bool TRRService::ConfirmationContext::HandleEvent(ConfirmationEvent aEvent,
|
|||
};
|
||||
|
||||
auto maybeConfirm = [&](const char* aReason) {
|
||||
service->mLock.AssertCurrentThreadOwns();
|
||||
if (TRR_DISABLED(mode) || mState == CONFIRM_DISABLED || mTask) {
|
||||
LOG(
|
||||
("TRRService:MaybeConfirm(%s) mode=%d, mTask=%p "
|
||||
|
@ -819,7 +825,7 @@ bool TRRService::ConfirmationContext::HandleEvent(ConfirmationEvent aEvent,
|
|||
|
||||
bool TRRService::MaybeBootstrap(const nsACString& aPossible,
|
||||
nsACString& aResult) {
|
||||
MutexAutoLock lock(mLock);
|
||||
MutexSingleWriterAutoLock lock(mLock);
|
||||
if (mMode == nsIDNSService::MODE_TRROFF || mBootstrapAddr.IsEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
@ -919,15 +925,13 @@ bool TRRService::IsExcludedFromTRR(const nsACString& aHost) {
|
|||
// This method may be called off the main thread. We need to lock so
|
||||
// mExcludedDomains and mDNSSuffixDomains don't change while this code
|
||||
// is running.
|
||||
MutexAutoLock lock(mLock);
|
||||
MutexSingleWriterAutoLock lock(mLock);
|
||||
|
||||
return IsExcludedFromTRR_unlocked(aHost);
|
||||
}
|
||||
|
||||
bool TRRService::IsExcludedFromTRR_unlocked(const nsACString& aHost) {
|
||||
if (!NS_IsMainThread()) {
|
||||
mLock.AssertCurrentThreadOwns();
|
||||
}
|
||||
mLock.AssertOnWritingThreadOrHeld();
|
||||
|
||||
int32_t dot = 0;
|
||||
// iteratively check the sub-domain of |aHost|
|
||||
|
@ -1008,7 +1012,7 @@ void TRRService::AddToBlocklist(const nsACString& aHost,
|
|||
|
||||
NS_IMETHODIMP
|
||||
TRRService::ConfirmationContext::Notify(nsITimer* aTimer) {
|
||||
MutexAutoLock lock(OwningObject()->mLock);
|
||||
MutexSingleWriterAutoLock lock(OwningObject()->mLock);
|
||||
if (aTimer == mTimer) {
|
||||
HandleEvent(ConfirmationEvent::Retry, lock);
|
||||
return NS_OK;
|
||||
|
@ -1128,7 +1132,7 @@ void TRRService::ConfirmationContext::RecordTRRStatus(nsresult aChannelStatus) {
|
|||
}
|
||||
|
||||
void TRRService::ConfirmationContext::RecordEvent(const char* aReason,
|
||||
const MutexAutoLock&) {
|
||||
const MutexSingleWriterAutoLock&) {
|
||||
// Reset the confirmation context attributes
|
||||
// Only resets the attributes that we keep for telemetry purposes.
|
||||
auto reset = [&]() {
|
||||
|
@ -1213,7 +1217,7 @@ void TRRService::ConfirmationContext::RequestCompleted(
|
|||
void TRRService::ConfirmationContext::CompleteConfirmation(nsresult aStatus,
|
||||
TRR* aTRRRequest) {
|
||||
{
|
||||
MutexAutoLock lock(OwningObject()->mLock);
|
||||
MutexSingleWriterAutoLock lock(OwningObject()->mLock);
|
||||
// Ignore confirmations that dont match the pending task.
|
||||
if (mTask != aTRRRequest) {
|
||||
return;
|
||||
|
|
|
@ -31,7 +31,8 @@ class TRRServiceParent;
|
|||
class TRRService : public TRRServiceBase,
|
||||
public nsIObserver,
|
||||
public nsSupportsWeakReference,
|
||||
public AHostResolver {
|
||||
public AHostResolver,
|
||||
public SingleWriterLockOwner {
|
||||
public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_NSIOBSERVER
|
||||
|
@ -40,6 +41,8 @@ class TRRService : public TRRServiceBase,
|
|||
TRRService();
|
||||
static TRRService* Get();
|
||||
|
||||
bool OnWritingThread() const override { return NS_IsMainThread(); }
|
||||
|
||||
nsresult Init();
|
||||
nsresult Start();
|
||||
bool Enabled(nsIRequest::TRRMode aRequestMode = nsIRequest::TRR_DEFAULT_MODE);
|
||||
|
@ -119,11 +122,11 @@ class TRRService : public TRRServiceBase,
|
|||
void AddEtcHosts(const nsTArray<nsCString>&);
|
||||
|
||||
bool mInitialized{false};
|
||||
Mutex mLock MOZ_UNANNOTATED{"TRRService"};
|
||||
MutexSingleWriter mLock;
|
||||
|
||||
nsCString mPrivateCred; // main thread only
|
||||
nsCString mConfirmationNS{"example.com"_ns};
|
||||
nsCString mBootstrapAddr;
|
||||
nsCString mConfirmationNS GUARDED_BY(mLock){"example.com"_ns};
|
||||
nsCString mBootstrapAddr GUARDED_BY(mLock);
|
||||
|
||||
Atomic<bool, Relaxed> mCaptiveIsPassed{
|
||||
false}; // set when captive portal check is passed
|
||||
|
@ -137,9 +140,9 @@ class TRRService : public TRRServiceBase,
|
|||
"DataMutex::TRRBlocklist"};
|
||||
|
||||
// A set of domains that we should not use TRR for.
|
||||
nsTHashSet<nsCString> mExcludedDomains;
|
||||
nsTHashSet<nsCString> mDNSSuffixDomains;
|
||||
nsTHashSet<nsCString> mEtcHostsDomains;
|
||||
nsTHashSet<nsCString> mExcludedDomains GUARDED_BY(mLock);
|
||||
nsTHashSet<nsCString> mDNSSuffixDomains GUARDED_BY(mLock);
|
||||
nsTHashSet<nsCString> mEtcHostsDomains GUARDED_BY(mLock);
|
||||
|
||||
enum class ConfirmationEvent {
|
||||
Init,
|
||||
|
@ -238,7 +241,7 @@ class TRRService : public TRRServiceBase,
|
|||
public:
|
||||
// Called when a confirmation completes successfully or when the
|
||||
// confirmation context changes.
|
||||
void RecordEvent(const char* aReason, const MutexAutoLock&);
|
||||
void RecordEvent(const char* aReason, const MutexSingleWriterAutoLock&);
|
||||
|
||||
// Called when a confirmation request is completed. The status is recorded
|
||||
// in the results.
|
||||
|
@ -253,7 +256,8 @@ class TRRService : public TRRServiceBase,
|
|||
// Returns true when handling the event caused a new confirmation task to be
|
||||
// dispatched.
|
||||
bool HandleEvent(ConfirmationEvent aEvent);
|
||||
bool HandleEvent(ConfirmationEvent aEvent, const MutexAutoLock&);
|
||||
bool HandleEvent(ConfirmationEvent aEvent,
|
||||
const MutexSingleWriterAutoLock&);
|
||||
|
||||
void SetCaptivePortalStatus(int32_t aStatus) {
|
||||
mCaptivePortalStatus = aStatus;
|
||||
|
@ -289,7 +293,7 @@ class TRRService : public TRRServiceBase,
|
|||
public:
|
||||
// Called when a confirmation completes successfully or when the
|
||||
// confirmation context changes.
|
||||
void RecordEvent(const char* aReason, const MutexAutoLock& aLock) {
|
||||
void RecordEvent(const char* aReason, const MutexSingleWriterAutoLock& aLock) {
|
||||
mConfirmation.RecordEvent(aReason, aLock);
|
||||
}
|
||||
|
||||
|
@ -313,7 +317,8 @@ class TRRService : public TRRServiceBase,
|
|||
return mConfirmation.HandleEvent(aEvent);
|
||||
}
|
||||
|
||||
bool HandleEvent(ConfirmationEvent aEvent, const MutexAutoLock& lock) {
|
||||
bool HandleEvent(ConfirmationEvent aEvent,
|
||||
const MutexSingleWriterAutoLock& lock) {
|
||||
return mConfirmation.HandleEvent(aEvent, lock);
|
||||
}
|
||||
|
||||
|
|
|
@ -70,7 +70,7 @@ class TRRServiceBase : public nsIProxyConfigChangedCallback {
|
|||
void RegisterProxyChangeListener();
|
||||
void UnregisterProxyChangeListener();
|
||||
|
||||
nsCString mPrivateURI;
|
||||
nsCString mPrivateURI; // protected by mMutex
|
||||
// Pref caches should only be used on the main thread.
|
||||
nsCString mURIPref;
|
||||
nsCString mRolloutURIPref;
|
||||
|
|
|
@ -175,7 +175,7 @@ nsHostResolver::nsHostResolver(uint32_t maxCacheEntries,
|
|||
|
||||
nsHostResolver::~nsHostResolver() = default;
|
||||
|
||||
nsresult nsHostResolver::Init() {
|
||||
nsresult nsHostResolver::Init() NO_THREAD_SAFETY_ANALYSIS {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
if (NS_FAILED(GetAddrInfoInit())) {
|
||||
return NS_ERROR_FAILURE;
|
||||
|
@ -1076,6 +1076,7 @@ void nsHostResolver::ComputeEffectiveTRRMode(nsHostRecord* aRec) {
|
|||
nsresult nsHostResolver::NameLookup(nsHostRecord* rec,
|
||||
const mozilla::MutexAutoLock& aLock) {
|
||||
LOG(("NameLookup host:%s af:%" PRId16, rec->host.get(), rec->af));
|
||||
mLock.AssertCurrentThreadOwns();
|
||||
|
||||
if (rec->flags & RES_IP_HINT) {
|
||||
LOG(("Skip lookup if RES_IP_HINT is set\n"));
|
||||
|
|
|
@ -211,7 +211,7 @@ class nsHostResolver : public nsISupports, public AHostResolver {
|
|||
// Records true if the TRR service is enabled for the record's effective
|
||||
// TRR mode. Also records the TRRSkipReason when the TRR service is not
|
||||
// available/enabled.
|
||||
bool TRRServiceEnabledForRecord(nsHostRecord* aRec);
|
||||
bool TRRServiceEnabledForRecord(nsHostRecord* aRec) REQUIRES(mLock);
|
||||
|
||||
private:
|
||||
explicit nsHostResolver(uint32_t maxCacheEntries,
|
||||
|
@ -229,10 +229,12 @@ class nsHostResolver : public nsISupports, public AHostResolver {
|
|||
const nsACString& aOriginsuffix,
|
||||
mozilla::net::TRRSkippedReason aReason,
|
||||
mozilla::net::TRR* aTRRRequest,
|
||||
const mozilla::MutexAutoLock& aLock);
|
||||
const mozilla::MutexAutoLock& aLock)
|
||||
REQUIRES(mLock);
|
||||
LookupStatus CompleteLookupByTypeLocked(
|
||||
nsHostRecord*, nsresult, mozilla::net::TypeRecordResultType& aResult,
|
||||
uint32_t aTtl, bool pb, const mozilla::MutexAutoLock& aLock);
|
||||
uint32_t aTtl, bool pb, const mozilla::MutexAutoLock& aLock)
|
||||
REQUIRES(mLock);
|
||||
nsresult Init();
|
||||
static void ComputeEffectiveTRRMode(nsHostRecord* aRec);
|
||||
nsresult NativeLookup(nsHostRecord* aRec,
|
||||
|
@ -244,21 +246,24 @@ class nsHostResolver : public nsISupports, public AHostResolver {
|
|||
nsresult NameLookup(nsHostRecord* aRec, const mozilla::MutexAutoLock& aLock);
|
||||
bool GetHostToLookup(AddrHostRecord** result);
|
||||
void MaybeRenewHostRecordLocked(nsHostRecord* aRec,
|
||||
const mozilla::MutexAutoLock& aLock);
|
||||
const mozilla::MutexAutoLock& aLock)
|
||||
REQUIRES(mLock);
|
||||
|
||||
// Cancels host records in the pending queue and also
|
||||
// calls CompleteLookup with the NS_ERROR_ABORT result code.
|
||||
void ClearPendingQueue(mozilla::LinkedList<RefPtr<nsHostRecord>>& aPendingQ);
|
||||
nsresult ConditionallyCreateThread(nsHostRecord* rec);
|
||||
nsresult ConditionallyCreateThread(nsHostRecord* rec) REQUIRES(mLock);
|
||||
|
||||
/**
|
||||
* Starts a new lookup in the background for entries that are in the grace
|
||||
* period with a failed connect or all cached entries are negative.
|
||||
*/
|
||||
nsresult ConditionallyRefreshRecord(nsHostRecord* rec, const nsACString& host,
|
||||
const mozilla::MutexAutoLock& aLock);
|
||||
const mozilla::MutexAutoLock& aLock)
|
||||
REQUIRES(mLock);
|
||||
|
||||
void AddToEvictionQ(nsHostRecord* rec, const mozilla::MutexAutoLock& aLock);
|
||||
void AddToEvictionQ(nsHostRecord* rec, const mozilla::MutexAutoLock& aLock)
|
||||
REQUIRES(mLock);
|
||||
|
||||
void ThreadFunc();
|
||||
|
||||
|
@ -266,7 +271,8 @@ class nsHostResolver : public nsISupports, public AHostResolver {
|
|||
already_AddRefed<nsHostRecord> FromCache(nsHostRecord* aRec,
|
||||
const nsACString& aHost,
|
||||
uint16_t aType, nsresult& aStatus,
|
||||
const mozilla::MutexAutoLock& aLock);
|
||||
const mozilla::MutexAutoLock& aLock)
|
||||
REQUIRES(mLock);
|
||||
// Called when the host name is an IP address and has been passed.
|
||||
already_AddRefed<nsHostRecord> FromCachedIPLiteral(nsHostRecord* aRec);
|
||||
// Like the above function, but the host name is not parsed to NetAddr yet.
|
||||
|
@ -276,7 +282,7 @@ class nsHostResolver : public nsISupports, public AHostResolver {
|
|||
already_AddRefed<nsHostRecord> FromUnspecEntry(
|
||||
nsHostRecord* aRec, const nsACString& aHost, const nsACString& aTrrServer,
|
||||
const nsACString& aOriginSuffix, uint16_t aType, uint16_t aFlags,
|
||||
uint16_t af, bool aPb, nsresult& aStatus);
|
||||
uint16_t af, bool aPb, nsresult& aStatus) REQUIRES(mLock);
|
||||
|
||||
enum {
|
||||
METHOD_HIT = 1,
|
||||
|
@ -292,21 +298,22 @@ class nsHostResolver : public nsISupports, public AHostResolver {
|
|||
uint32_t mDefaultCacheLifetime = 0; // granularity seconds
|
||||
uint32_t mDefaultGracePeriod = 0; // granularity seconds
|
||||
// mutable so SizeOfIncludingThis can be const
|
||||
mutable Mutex mLock MOZ_UNANNOTATED{"nsHostResolver.mLock"};
|
||||
mutable Mutex mLock{"nsHostResolver.mLock"};
|
||||
CondVar mIdleTaskCV;
|
||||
nsRefPtrHashtable<nsGenericHashKey<nsHostKey>, nsHostRecord> mRecordDB;
|
||||
nsRefPtrHashtable<nsGenericHashKey<nsHostKey>, nsHostRecord> mRecordDB
|
||||
GUARDED_BY(mLock);
|
||||
PRTime mCreationTime;
|
||||
mozilla::TimeDuration mLongIdleTimeout;
|
||||
mozilla::TimeDuration mShortIdleTimeout;
|
||||
|
||||
RefPtr<nsIThreadPool> mResolverThreads;
|
||||
mozilla::net::HostRecordQueue mQueue;
|
||||
mozilla::Atomic<bool> mShutdown{true};
|
||||
mozilla::Atomic<uint32_t> mNumIdleTasks{0};
|
||||
mozilla::Atomic<uint32_t> mActiveTaskCount{0};
|
||||
mozilla::Atomic<uint32_t> mActiveAnyThreadCount{0};
|
||||
RefPtr<mozilla::net::NetworkConnectivityService>
|
||||
mNCS; // reference to a singleton
|
||||
mozilla::net::HostRecordQueue mQueue GUARDED_BY(mLock);
|
||||
mozilla::Atomic<bool> mShutdown GUARDED_BY(mLock){true};
|
||||
mozilla::Atomic<uint32_t> mNumIdleTasks GUARDED_BY(mLock){0};
|
||||
mozilla::Atomic<uint32_t> mActiveTaskCount GUARDED_BY(mLock){0};
|
||||
mozilla::Atomic<uint32_t> mActiveAnyThreadCount GUARDED_BY(mLock){0};
|
||||
|
||||
// Set the expiration time stamps appropriately.
|
||||
void PrepareRecordExpirationAddrRecord(AddrHostRecord* rec) const;
|
||||
|
|
|
@ -84,7 +84,7 @@ static const char* gCallbackPrefs[] = {
|
|||
|
||||
nsresult nsIDNService::Init() {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MutexAutoLock lock(mLock);
|
||||
MutexSingleWriterAutoLock lock(mLock);
|
||||
|
||||
nsCOMPtr<nsIPrefService> prefs(do_GetService(NS_PREFSERVICE_CONTRACTID));
|
||||
if (prefs) {
|
||||
|
@ -137,8 +137,9 @@ void nsIDNService::prefsChanged(const char* pref) {
|
|||
}
|
||||
}
|
||||
|
||||
nsIDNService::nsIDNService() {
|
||||
nsIDNService::nsIDNService() : mLock("IDNSService", this) {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
mLock.AssertOnWritingThread();
|
||||
|
||||
auto createResult =
|
||||
mozilla::intl::IDNA::TryCreate(kIDNA2008_DefaultProcessingType);
|
||||
|
@ -148,6 +149,7 @@ nsIDNService::nsIDNService() {
|
|||
|
||||
nsIDNService::~nsIDNService() {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
mLock.AssertOnWritingThread();
|
||||
|
||||
Preferences::UnregisterPrefixCallbacks(PrefChanged, gCallbackPrefs, this);
|
||||
}
|
||||
|
@ -392,20 +394,24 @@ NS_IMETHODIMP nsIDNService::Normalize(const nsACString& input,
|
|||
|
||||
namespace {
|
||||
|
||||
class MOZ_STACK_CLASS MutexSettableAutoUnlock final {
|
||||
template <typename T>
|
||||
class CAPABILITY MOZ_STACK_CLASS MutexSettableAutoUnlock final {
|
||||
private:
|
||||
Mutex* mMutex = nullptr;
|
||||
T* mMutex = nullptr;
|
||||
|
||||
public:
|
||||
MutexSettableAutoUnlock() = default;
|
||||
|
||||
void Acquire(mozilla::Mutex& aMutex) NO_THREAD_SAFETY_ANALYSIS {
|
||||
void Acquire(T& aMutex) CAPABILITY_ACQUIRE(aMutex) {
|
||||
MOZ_ASSERT(!mMutex);
|
||||
mMutex = &aMutex;
|
||||
mMutex->Lock();
|
||||
aMutex.Lock();
|
||||
}
|
||||
|
||||
~MutexSettableAutoUnlock() {
|
||||
// Since this is commonly used in "if (!NS_IsMainThread())", if we make
|
||||
// this CAPABILITY_RELEASE(mMutex) we'll generate warnings on each return.
|
||||
// We may still get a warning at the end of a function using this
|
||||
~MutexSettableAutoUnlock() CAPABILITY_ACQUIRE() {
|
||||
if (mMutex) {
|
||||
mMutex->Unlock();
|
||||
}
|
||||
|
@ -414,13 +420,15 @@ class MOZ_STACK_CLASS MutexSettableAutoUnlock final {
|
|||
|
||||
} // anonymous namespace
|
||||
|
||||
NS_IMETHODIMP nsIDNService::ConvertToDisplayIDN(const nsACString& input,
|
||||
bool* _isASCII,
|
||||
nsACString& _retval) {
|
||||
MutexSettableAutoUnlock lock;
|
||||
// conditional locks blow threadsafety's mind
|
||||
NS_IMETHODIMP nsIDNService::ConvertToDisplayIDN(
|
||||
const nsACString& input, bool* _isASCII,
|
||||
nsACString& _retval) NO_THREAD_SAFETY_ANALYSIS {
|
||||
MutexSettableAutoUnlock<MutexSingleWriter> lock;
|
||||
if (!NS_IsMainThread()) {
|
||||
lock.Acquire(mLock);
|
||||
}
|
||||
mLock.AssertOnWritingThreadOrHeld();
|
||||
|
||||
// If host is ACE, then convert to UTF-8 if the host is in the IDN whitelist.
|
||||
// Else, if host is already UTF-8, then make sure it is normalized per IDN.
|
||||
|
@ -490,7 +498,7 @@ NS_IMETHODIMP nsIDNService::ConvertToDisplayIDN(const nsACString& input,
|
|||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
} // Will generate a mutex still-held warning
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
@ -685,6 +693,8 @@ nsresult nsIDNService::decodeACE(const nsACString& in, nsACString& out,
|
|||
bool nsIDNService::isInWhitelist(const nsACString& host) {
|
||||
if (!NS_IsMainThread()) {
|
||||
mLock.AssertCurrentThreadOwns();
|
||||
} else {
|
||||
mLock.AssertOnWritingThread();
|
||||
}
|
||||
|
||||
if (mIDNUseWhitelist && mIDNWhitelistPrefBranch) {
|
||||
|
@ -716,6 +726,8 @@ bool nsIDNService::isInWhitelist(const nsACString& host) {
|
|||
bool nsIDNService::isLabelSafe(const nsAString& label) {
|
||||
if (!NS_IsMainThread()) {
|
||||
mLock.AssertCurrentThreadOwns();
|
||||
} else {
|
||||
mLock.AssertOnWritingThread();
|
||||
}
|
||||
|
||||
if (!isOnlySafeChars(PromiseFlatString(label), mIDNBlocklist)) {
|
||||
|
@ -895,6 +907,8 @@ static const int32_t scriptComboTable[13][9] = {
|
|||
bool nsIDNService::illegalScriptCombo(Script script, int32_t& savedScript) {
|
||||
if (!NS_IsMainThread()) {
|
||||
mLock.AssertCurrentThreadOwns();
|
||||
} else {
|
||||
mLock.AssertOnWritingThread();
|
||||
}
|
||||
|
||||
if (savedScript == -1) {
|
||||
|
|
|
@ -25,13 +25,16 @@ class nsIPrefBranch;
|
|||
//-----------------------------------------------------------------------------
|
||||
|
||||
class nsIDNService final : public nsIIDNService,
|
||||
public nsSupportsWeakReference {
|
||||
public nsSupportsWeakReference,
|
||||
public mozilla::SingleWriterLockOwner {
|
||||
public:
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
NS_DECL_NSIIDNSERVICE
|
||||
|
||||
nsIDNService();
|
||||
|
||||
bool OnWritingThread() const override { return NS_IsMainThread(); }
|
||||
|
||||
nsresult Init();
|
||||
|
||||
protected:
|
||||
|
@ -101,7 +104,7 @@ class nsIDNService final : public nsIIDNService,
|
|||
|
||||
static void PrefChanged(const char* aPref, void* aSelf) {
|
||||
auto* self = static_cast<nsIDNService*>(aSelf);
|
||||
mozilla::MutexAutoLock lock(self->mLock);
|
||||
mozilla::MutexSingleWriterAutoLock lock(self->mLock);
|
||||
self->prefsChanged(aPref);
|
||||
}
|
||||
|
||||
|
@ -165,15 +168,15 @@ class nsIDNService final : public nsIIDNService,
|
|||
|
||||
// We use this mutex to guard access to:
|
||||
// |mIDNBlocklist|, |mShowPunycode|, |mRestrictionProfile|,
|
||||
// |mIDNUseWhitelist|.
|
||||
// |mIDNUseWhitelist|, |mIDNWhitelistPrefBranch|.
|
||||
//
|
||||
// These members can only be updated on the main thread and
|
||||
// read on any thread. Therefore, acquiring the mutex is required
|
||||
// only for threads other than the main thread.
|
||||
mozilla::Mutex mLock MOZ_UNANNOTATED{"IDNService"};
|
||||
mozilla::MutexSingleWriter mLock;
|
||||
|
||||
// guarded by mLock
|
||||
nsTArray<mozilla::net::BlocklistRange> mIDNBlocklist;
|
||||
nsTArray<mozilla::net::BlocklistRange> mIDNBlocklist GUARDED_BY(mLock);
|
||||
|
||||
/**
|
||||
* Flag set by the pref network.IDN_show_punycode. When it is true,
|
||||
|
@ -182,7 +185,7 @@ class nsIDNService final : public nsIIDNService,
|
|||
*
|
||||
* guarded by mLock
|
||||
*/
|
||||
bool mShowPunycode = false;
|
||||
bool mShowPunycode GUARDED_BY(mLock) = false;
|
||||
|
||||
/**
|
||||
* Restriction-level Detection profiles defined in UTR 39
|
||||
|
@ -195,11 +198,11 @@ class nsIDNService final : public nsIIDNService,
|
|||
eModeratelyRestrictiveProfile
|
||||
};
|
||||
// guarded by mLock;
|
||||
restrictionProfile mRestrictionProfile{eASCIIOnlyProfile};
|
||||
restrictionProfile mRestrictionProfile GUARDED_BY(mLock){eASCIIOnlyProfile};
|
||||
// guarded by mLock;
|
||||
nsCOMPtr<nsIPrefBranch> mIDNWhitelistPrefBranch;
|
||||
nsCOMPtr<nsIPrefBranch> mIDNWhitelistPrefBranch GUARDED_BY(mLock);
|
||||
// guarded by mLock
|
||||
bool mIDNUseWhitelist = false;
|
||||
bool mIDNUseWhitelist GUARDED_BY(mLock) = false;
|
||||
};
|
||||
|
||||
#endif // nsIDNService_h__
|
||||
|
|
Загрузка…
Ссылка в новой задаче