summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--modules/libjar/nsJAR.cpp26
-rw-r--r--modules/libjar/nsJAR.h8
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;