Skip to content

fix(memory): Fix memory leak for audio events when pausing the game#2731

Open
Caball009 wants to merge 3 commits into
TheSuperHackers:mainfrom
Caball009:fix_memory_leak_audio_requests
Open

fix(memory): Fix memory leak for audio events when pausing the game#2731
Caball009 wants to merge 3 commits into
TheSuperHackers:mainfrom
Caball009:fix_memory_leak_audio_requests

Conversation

@Caball009
Copy link
Copy Markdown

Pausing the game leaks audio events that were in the audio request container at the time. This PR fixes that.

This code is called to get rid of some of the audio requests when pausing the game:

//Get rid of PLAY audio requests when pausing audio.
std::list<AudioRequest*>::iterator ait;
for (ait = m_audioRequests.begin(); ait != m_audioRequests.end(); /* empty */)
{
AudioRequest *req = (*ait);
if( req && req->m_request == AR_Play )
{
deleteInstance(req);
ait = m_audioRequests.erase(ait);
}
else
{
ait++;
}
}

AudioRequest::m_pendingEvent can be an owning raw pointer, though, which the destructor of AudioRequest should delete when needed. It currently doesn't, which is why the leak happens.

There's one exception where the ownership of the audio event is taken away from the audio request:

@Caball009 Caball009 added Minor Severity: Minor < Major < Critical < Blocker Gen Relates to Generals ZH Relates to Zero Hour Memory Is memory related Fix Is fixing something, but is not user facing labels May 19, 2026
@greptile-apps
Copy link
Copy Markdown

greptile-apps Bot commented May 19, 2026

Greptile Summary

This PR fixes a memory leak that occurred when the game was paused while audio play requests were queued in m_audioRequests. The root cause was that AudioRequest::~AudioRequest() did not delete m_pendingEvent even though the request could be the owning holder of that pointer.

  • Adds a destructor body to AudioRequest that conditionally deletes m_pendingEvent when m_usePendingEvent is true, and introduces releasePendingEvent() to transfer ownership away from the request before destruction.
  • Refactors playAudioEvent to accept AudioRequest* instead of a raw AudioEventRTS*, calling releasePendingEvent() at each of the three assignment sites where ownership moves to a PlayingAudio slot, leaving cleanup to the destructor on all early-exit paths (e.g., !info return).

Confidence Score: 5/5

Safe to merge — the fix correctly scopes ownership of the audio event to the AudioRequest destructor and uses a well-defined release idiom to transfer it to PlayingAudio at exactly one point per execution path.

The destructor addition and releasePendingEvent() method are straightforward and provably correct: every code path through playAudioEvent either leaves m_usePendingEvent true (destructor cleans up) or calls releasePendingEvent() exactly once before transferring the pointer to PlayingAudio (which cleans it up via releasePlayingAudio). No double-free or use-after-free paths were found.

No files require special attention.

Important Files Changed

Filename Overview
Core/GameEngine/Source/Common/Audio/AudioRequest.cpp Adds destructor that deletes m_pendingEvent when owned, and releasePendingEvent() for safe ownership transfer — both correctly conditioned on m_usePendingEvent.
Core/GameEngine/Include/Common/AudioRequest.h Declares releasePendingEvent() in the AudioRequest struct; no structural issues.
Core/GameEngineDevice/Source/MilesAudioDevice/MilesAudioManager.cpp playAudioEvent signature changed to take AudioRequest*; releasePendingEvent() called at exactly one site per execution path (stream, 3D, 2D), leaving the destructor responsible for all early-exit cleanup.
Core/GameEngineDevice/Include/MilesAudioDevice/MilesAudioManager.h Updates playAudioEvent declaration to match new AudioRequest* parameter — straightforward signature update.

Sequence Diagram

sequenceDiagram
    participant PRL as processRequestList
    participant AR as AudioRequest
    participant PAE as playAudioEvent
    participant PA as PlayingAudio

    PRL->>AR: deleteInstance(req) [pause path]
    Note over AR: destructor sees m_usePendingEvent==true, deletes m_pendingEvent

    PRL->>PAE: playAudioEvent(req) [normal path]
    PAE->>PAE: "event = req->m_pendingEvent (read only)"
    alt early return due to missing info
        PAE-->>PRL: return
        Note over AR: destructor deletes m_pendingEvent since m_usePendingEvent still true
    else stream or 3D or 2D sample branch
        PAE->>AR: releasePendingEvent()
        Note over AR: sets m_usePendingEvent=false and m_pendingEvent=nullptr
        AR-->>PAE: "AudioEventRTS* (ownership transferred)"
        PAE->>PA: "audio->m_audioEventRTS = event"
        Note over PA: releasePlayingAudio frees it later
    end
    PRL->>AR: deleteInstance(req)
    Note over AR: destructor sees m_usePendingEvent==false, no double-delete
Loading

Reviews (6): Last reviewed commit: "Reverted some of the changes to use 'eve..." | Re-trigger Greptile

Comment thread Core/GameEngineDevice/Source/MilesAudioDevice/MilesAudioManager.cpp Outdated
Comment thread Core/GameEngineDevice/Source/MilesAudioDevice/MilesAudioManager.cpp Outdated
@Caball009 Caball009 force-pushed the fix_memory_leak_audio_requests branch from 057637e to 977bd8b Compare May 19, 2026 21:15
Copy link
Copy Markdown

@xezon xezon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking good.

@Caball009 Caball009 force-pushed the fix_memory_leak_audio_requests branch from 977bd8b to afb337c Compare May 19, 2026 22:15
@Caball009
Copy link
Copy Markdown
Author

Rebased to include the fix for the CI Replay checker.

Comment thread Core/GameEngineDevice/Source/MilesAudioDevice/MilesAudioManager.cpp Outdated
@Caball009 Caball009 force-pushed the fix_memory_leak_audio_requests branch from 9e09418 to 08f2330 Compare May 20, 2026 17:01
Comment thread Core/GameEngine/Source/Common/Audio/AudioRequest.cpp Outdated
Comment thread Core/GameEngineDevice/Source/MilesAudioDevice/MilesAudioManager.cpp Outdated
@Caball009 Caball009 force-pushed the fix_memory_leak_audio_requests branch from 08f2330 to 130a39f Compare May 20, 2026 21:36
Copy link
Copy Markdown

@xezon xezon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking good

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Fix Is fixing something, but is not user facing Gen Relates to Generals Memory Is memory related Minor Severity: Minor < Major < Critical < Blocker ZH Relates to Zero Hour

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants