Bug 1753192 - Fix apparent negative leak of RequestedChunkRefCountedHolder - r=canaltinova

Once the buffers are combined, a RequestedChunkRefCountedHolder could be referenced from the Base Profiler, which is invisible to the leak catcher; then handed over to the Gecko Profiler where it will eventually be dereferenced, which is logged with the leak catcher, resulting in an apparent negative leak.
This is fixed by keeping all (de)references secret.

Differential Revision: https://phabricator.services.mozilla.com/D138238
This commit is contained in:
Gerald Squelart 2022-02-11 03:13:51 +00:00
parent adf6de3385
commit 6906b4d69a

View File

@ -14,7 +14,6 @@
#include "mozilla/ProfileBufferChunkManagerSingle.h"
#include "mozilla/ProfileBufferEntrySerialization.h"
#include "mozilla/ProfileChunkedBufferDetail.h"
#include "mozilla/RefCounted.h"
#include "mozilla/RefPtr.h"
#include "mozilla/ScopeExit.h"
#include "mozilla/Unused.h"
@ -1200,11 +1199,8 @@ class ProfileChunkedBuffer {
// asynchronously, and either side may be destroyed during the request.
// It cannot use the `ProfileChunkedBuffer` mutex, because that buffer and its
// mutex could be destroyed during the request.
class RequestedChunkRefCountedHolder
: public external::AtomicRefCounted<RequestedChunkRefCountedHolder> {
class RequestedChunkRefCountedHolder {
public:
MOZ_DECLARE_REFCOUNTED_TYPENAME(RequestedChunkRefCountedHolder)
enum class State { Unused, Requested, Fulfilled };
// Get the current state. Note that it may change after the function
@ -1250,9 +1246,32 @@ class ProfileChunkedBuffer {
return maybeChunk;
}
// Ref-counting implementation. Hand-rolled, because mozilla::RefCounted
// logs AddRefs and Releases in xpcom, but this object could be AddRef'd
// by the Base Profiler before xpcom starts, then Release'd by the Gecko
// Profiler in xpcom, leading to apparent negative leaks.
void AddRef() {
baseprofiler::detail::BaseProfilerAutoLock lock(mRequestMutex);
++mRefCount;
}
void Release() {
{
baseprofiler::detail::BaseProfilerAutoLock lock(mRequestMutex);
if (--mRefCount > 0) {
return;
}
}
delete this;
}
private:
~RequestedChunkRefCountedHolder() = default;
// Mutex guarding the following members.
mutable baseprofiler::detail::BaseProfilerMutex mRequestMutex;
int mRefCount = 0;
State mState = State::Unused;
UniquePtr<ProfileBufferChunk> mRequestedChunk;
};