Bug 1207753 - netwerk/dns thread-safety annotations r=necko-reviewers,dragana

Differential Revision: https://phabricator.services.mozilla.com/D130580
This commit is contained in:
Randell Jesup 2022-05-12 21:55:01 +00:00
Родитель 8da8a144a5
Коммит 39e3372695
9 изменённых файлов: 119 добавлений и 86 удалений

Просмотреть файл

@ -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__