diff options
-rw-r--r-- | modules/libjar/nsJAR.cpp | 26 | ||||
-rw-r--r-- | modules/libjar/nsJAR.h | 8 |
2 files changed, 23 insertions, 11 deletions
diff --git a/modules/libjar/nsJAR.cpp b/modules/libjar/nsJAR.cpp index c7f5ebc96..aa673ea50 100644 --- a/modules/libjar/nsJAR.cpp +++ b/modules/libjar/nsJAR.cpp @@ -97,11 +97,27 @@ NS_IMPL_QUERY_INTERFACE(nsJAR, nsIZipReader) NS_IMPL_ADDREF(nsJAR) // Custom Release method works with nsZipReaderCache... +// Release might be called from multi-thread, we have to +// take this function carefully to avoid delete-after-use. MozExternalRefCountType nsJAR::Release(void) { nsrefcnt count; NS_PRECONDITION(0 != mRefCnt, "dup release"); - count = --mRefCnt; + + nsRefPtr<nsZipReaderCache> cache; + if (mRefCnt == 2) { // don't use a lock too frequently + // Use a mutex here to guarantee mCache is not racing and the target instance + // is still valid to increase ref-count. + MutexAutoLock lock(mLock); + cache = mCache; + mCache = nullptr; + } + if (cache) { + nsresult rv = cache->ReleaseZip(this); + MOZ_ASSERT(NS_SUCCEEDED(rv), "failed to release zip file"); + } + + count = --mRefCnt; // don't access any member variable after this line NS_LOG_RELEASE(this, count, "nsJAR"); if (0 == count) { mRefCnt = 1; /* stabilize */ @@ -110,13 +126,7 @@ MozExternalRefCountType nsJAR::Release(void) delete this; return 0; } - else if (1 == count && mCache) { -#ifdef DEBUG - nsresult rv = -#endif - mCache->ReleaseZip(this); - NS_ASSERTION(NS_SUCCEEDED(rv), "failed to release zip file"); - } + return count; } diff --git a/modules/libjar/nsJAR.h b/modules/libjar/nsJAR.h index 167054a2f..c0a238a21 100644 --- a/modules/libjar/nsJAR.h +++ b/modules/libjar/nsJAR.h @@ -12,6 +12,7 @@ #include "prlog.h" #include "prinrval.h" +#include "mozilla/Atomics.h" #include "mozilla/Mutex.h" #include "nsIComponentManager.h" #include "nsCOMPtr.h" @@ -91,8 +92,9 @@ class nsJAR final : public nsIZipReader mReleaseTime = PR_INTERVAL_NO_TIMEOUT; } - void SetZipReaderCache(nsZipReaderCache* cache) { - mCache = cache; + void SetZipReaderCache(nsZipReaderCache* aCache) { + mozilla::MutexAutoLock lock(mLock); + mCache = aCache; } nsresult GetNSPRFileDesc(PRFileDesc** aNSPRFileDesc); @@ -110,7 +112,7 @@ class nsJAR final : public nsIZipReader int16_t mGlobalStatus; // Global signature verification status PRIntervalTime mReleaseTime; // used by nsZipReaderCache for flushing entries nsZipReaderCache* mCache; // if cached, this points to the cache it's contained in - mozilla::Mutex mLock; + mozilla::Mutex mLock; // protect mCache and mZip int64_t mMtime; int32_t mTotalItemsInManifest; bool mOpened; |