mirror of
https://github.com/isledecomp/isle-portable.git
synced 2026-01-18 13:21:16 +00:00
Fix MxDSBuffer leak
This commit is contained in:
parent
2f2446af87
commit
933c5bb1a4
@ -91,6 +91,12 @@ class MxDSBuffer : public MxCore {
|
|||||||
|
|
||||||
void SetUnk30(MxDSStreamingAction* p_unk0x30) { m_unk0x30 = p_unk0x30; }
|
void SetUnk30(MxDSStreamingAction* p_unk0x30) { m_unk0x30 = p_unk0x30; }
|
||||||
|
|
||||||
|
void SetSourceBuffer(MxDSBuffer* p_sourceBuffer)
|
||||||
|
{
|
||||||
|
m_sourceBuffer = p_sourceBuffer;
|
||||||
|
m_sourceBuffer->AddRef(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
// SYNTHETIC: LEGO1 0x100c6510
|
// SYNTHETIC: LEGO1 0x100c6510
|
||||||
// SYNTHETIC: BETA10 0x10158530
|
// SYNTHETIC: BETA10 0x10158530
|
||||||
// MxDSBuffer::`scalar deleting destructor'
|
// MxDSBuffer::`scalar deleting destructor'
|
||||||
@ -107,6 +113,7 @@ class MxDSBuffer : public MxCore {
|
|||||||
MxU32 m_writeOffset; // 0x28
|
MxU32 m_writeOffset; // 0x28
|
||||||
MxU32 m_bytesRemaining; // 0x2c
|
MxU32 m_bytesRemaining; // 0x2c
|
||||||
MxDSStreamingAction* m_unk0x30; // 0x30
|
MxDSStreamingAction* m_unk0x30; // 0x30
|
||||||
|
MxDSBuffer* m_sourceBuffer;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // MXDSBUFFER_H
|
#endif // MXDSBUFFER_H
|
||||||
|
|||||||
@ -28,6 +28,7 @@ MxDSBuffer::MxDSBuffer()
|
|||||||
m_bytesRemaining = 0;
|
m_bytesRemaining = 0;
|
||||||
m_mode = e_preallocated;
|
m_mode = e_preallocated;
|
||||||
m_unk0x30 = 0;
|
m_unk0x30 = 0;
|
||||||
|
m_sourceBuffer = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// FUNCTION: LEGO1 0x100c6530
|
// FUNCTION: LEGO1 0x100c6530
|
||||||
@ -36,6 +37,10 @@ MxDSBuffer::~MxDSBuffer()
|
|||||||
{
|
{
|
||||||
assert(m_referenceCount == 0);
|
assert(m_referenceCount == 0);
|
||||||
|
|
||||||
|
if (m_sourceBuffer) {
|
||||||
|
m_sourceBuffer->ReleaseRef(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
if (m_pBuffer != NULL) {
|
if (m_pBuffer != NULL) {
|
||||||
switch (m_mode) {
|
switch (m_mode) {
|
||||||
case e_allocate:
|
case e_allocate:
|
||||||
@ -267,6 +272,28 @@ MxResult MxDSBuffer::ParseChunk(
|
|||||||
return FAILURE;
|
return FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// START FIX: Ref-Counting Backpressure for Split Chunks
|
||||||
|
//
|
||||||
|
// PROBLEM: When a `DS_CHUNK_SPLIT` is found, the temporary `MxStreamChunk`
|
||||||
|
// header that holds a reference to the source buffer is immediately
|
||||||
|
// destroyed. This prematurely releases the reference, causing the source
|
||||||
|
// buffer's ref-count to drop to zero.
|
||||||
|
//
|
||||||
|
// EFFECT: The source buffer is freed immediately instead of being kept
|
||||||
|
// alive on the m_list0x74 "keep-alive" list. This breaks the natural
|
||||||
|
// ref-counting backpressure mechanism, as the controller is blind to the
|
||||||
|
// downstream workload and keeps reading new data from the stream at full
|
||||||
|
// speed, eventually leading to a memory leak.
|
||||||
|
//
|
||||||
|
// SOLUTION: We explicitly link the new reassembly buffer to the original
|
||||||
|
// source buffer. We then add an artificial reference to the source buffer.
|
||||||
|
// This reference is designed to be released by the reassembly buffer's
|
||||||
|
// destructor, ensuring the source buffer is kept alive for the correct
|
||||||
|
// duration and that the backpressure system functions as intended.
|
||||||
|
if (p_header->GetBuffer()) {
|
||||||
|
buffer->SetSourceBuffer(p_header->GetBuffer());
|
||||||
|
}
|
||||||
|
|
||||||
MxU16* flags = MxStreamChunk::IntoFlags(buffer->GetBuffer());
|
MxU16* flags = MxStreamChunk::IntoFlags(buffer->GetBuffer());
|
||||||
*flags = p_header->GetChunkFlags() & ~DS_CHUNK_SPLIT;
|
*flags = p_header->GetChunkFlags() & ~DS_CHUNK_SPLIT;
|
||||||
|
|
||||||
@ -409,9 +436,7 @@ MxU8 MxDSBuffer::ReleaseRef(MxDSChunk*)
|
|||||||
// FUNCTION: LEGO1 0x100c6ee0
|
// FUNCTION: LEGO1 0x100c6ee0
|
||||||
void MxDSBuffer::AddRef(MxDSChunk* p_chunk)
|
void MxDSBuffer::AddRef(MxDSChunk* p_chunk)
|
||||||
{
|
{
|
||||||
if (p_chunk) {
|
m_referenceCount++;
|
||||||
m_referenceCount++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// FUNCTION: LEGO1 0x100c6ef0
|
// FUNCTION: LEGO1 0x100c6ef0
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user