зеркало из https://github.com/mozilla/gecko-dev.git
Bug 897723 - Allow faulty.lib's on-demand decompression to be reentrant. r=nfroyd
This commit is contained in:
Родитель
1591b955e1
Коммит
92fbf52fbf
|
@ -344,7 +344,11 @@ MappableSeekableZStream::Create(const char *name, Zip *zip,
|
|||
mozilla::ScopedDeletePtr<MappableSeekableZStream> mappable;
|
||||
mappable = new MappableSeekableZStream(zip);
|
||||
|
||||
if (pthread_mutex_init(&mappable->mutex, NULL))
|
||||
pthread_mutexattr_t recursiveAttr;
|
||||
pthread_mutexattr_init(&recursiveAttr);
|
||||
pthread_mutexattr_settype(&recursiveAttr, PTHREAD_MUTEX_RECURSIVE);
|
||||
|
||||
if (pthread_mutex_init(&mappable->mutex, &recursiveAttr))
|
||||
return NULL;
|
||||
|
||||
if (!mappable->zStream.Init(stream->GetBuffer(), stream->GetSize()))
|
||||
|
@ -466,6 +470,19 @@ MappableSeekableZStream::ensure(const void *addr)
|
|||
|
||||
length = PageAlignedSize(length);
|
||||
|
||||
/* The following lock can be re-acquired by the thread holding it.
|
||||
* If this happens, it means the following code is interrupted somehow by
|
||||
* some signal, and ends up retriggering a chunk decompression for the
|
||||
* same MappableSeekableZStream.
|
||||
* If the chunk to decompress is different the second time, then everything
|
||||
* is safe as the only common data touched below is chunkAvailNum, and it is
|
||||
* atomically updated (leaving out any chance of an interruption while it is
|
||||
* updated affecting the result). If the chunk to decompress is the same, the
|
||||
* worst thing that can happen is chunkAvailNum being incremented one too
|
||||
* many times, which doesn't affect functionality. The chances of it
|
||||
* happening being pretty slim, and the effect being harmless, we can just
|
||||
* ignore the issue. Other than that, we'd just be wasting time decompressing
|
||||
* the same chunk twice. */
|
||||
AutoLock lock(&mutex);
|
||||
|
||||
/* The very first page is mapped and accessed separately of the rest, and
|
||||
|
@ -522,7 +539,7 @@ MappableSeekableZStream::stats(const char *when, const char *name) const
|
|||
{
|
||||
size_t nEntries = zStream.GetChunksNum();
|
||||
DEBUG_LOG("%s: %s; %" PRIdSize "/%" PRIdSize " chunks decompressed",
|
||||
name, when, chunkAvailNum, nEntries);
|
||||
name, when, static_cast<size_t>(chunkAvailNum), nEntries);
|
||||
|
||||
size_t len = 64;
|
||||
mozilla::ScopedDeleteArray<char> map;
|
||||
|
|
|
@ -265,7 +265,7 @@ private:
|
|||
mozilla::ScopedDeleteArray<unsigned char> chunkAvail;
|
||||
|
||||
/* Number of chunks that have already been decompressed. */
|
||||
size_t chunkAvailNum;
|
||||
mozilla::Atomic<size_t> chunkAvailNum;
|
||||
|
||||
/* Mutex protecting decompression */
|
||||
pthread_mutex_t mutex;
|
||||
|
|
Загрузка…
Ссылка в новой задаче