Skip to content

Commit a7fad3b

Browse files
committed
fix(milesaudiomanager): Prevent multithread crashing in MilesAudioManager (TheSuperHackers#2718)
1 parent b0becc4 commit a7fad3b

4 files changed

Lines changed: 314 additions & 217 deletions

File tree

Core/GameEngineDevice/Include/MilesAudioDevice/MilesAudioManager.h

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include "Common/AsciiString.h"
2424
#include "Common/GameAudio.h"
2525
#include "mss/mss.h"
26+
#include "mutex.h"
2627

2728
class AudioEventRTS;
2829

@@ -39,7 +40,8 @@ enum PlayingAudioType CPP_11(: Int)
3940
enum PlayingStatus CPP_11(: Int)
4041
{
4142
PS_Playing,
42-
PS_Stopped,
43+
PS_Stopping, ///< Is about to be stopped
44+
PS_Stopped, ///< Is about to be released
4345
};
4446

4547
enum PlayingWhich CPP_11(: Int)
@@ -63,8 +65,8 @@ struct PlayingAudio
6365
void *m_file; // The file that was opened to play this
6466
PlayingAudioType m_type;
6567
volatile PlayingStatus m_status; // This member is adjusted by another running thread.
66-
Int m_framesFaded;
67-
Bool m_requestStop;
68+
Short m_framesFaded;
69+
Bool m_fade;
6870
Bool m_cleanupAudioEventRTS;
6971

7072
PlayingAudio()
@@ -74,9 +76,11 @@ struct PlayingAudio
7476
, m_type(PAT_INVALID)
7577
, m_status(PS_Playing)
7678
, m_framesFaded(0)
77-
, m_requestStop(false)
79+
, m_fade(false)
7880
, m_cleanupAudioEventRTS(true)
7981
{}
82+
83+
static_assert(sizeof(m_status) == sizeof(long), "Must be size of long, because it is used with Interlocked functions");
8084
};
8185

8286
struct ProviderInfo
@@ -258,10 +262,13 @@ class MilesAudioManager : public AudioManager
258262
PlayingAudio *allocatePlayingAudio();
259263
void releaseMilesHandles( PlayingAudio *release );
260264
void releasePlayingAudio( PlayingAudio *release );
265+
void stopPlayingAudio( PlayingAudio *release );
266+
void fadePlayingAudio( PlayingAudio *playing );
261267

262268
PlayingAudio *findActiveMusic( const AsciiString *trackName = nullptr );
263269
const PlayingAudio *findActiveMusic( const AsciiString* trackName = nullptr ) const;
264270

271+
void releasePlayingAudioInListIfStopped(std::list<PlayingAudio *> &list, CriticalSectionClass &cs);
265272
void stopAllAudioImmediately();
266273
void freeAllMilesHandles();
267274

@@ -307,6 +314,13 @@ class MilesAudioManager : public AudioManager
307314
// Currently fading music. We just let it finish fading, then release it.
308315
std::list<PlayingAudio *> m_fadingAudio;
309316

317+
// TheSuperHackers @fix Erasing from PlayingAudio lists on main thread is not safe when the MSS Timer thread
318+
// needs to iterate the same lists. The critical sections are used to guard writes that will invalidate iterators.
319+
CriticalSectionClass m_playingSoundsCS;
320+
CriticalSectionClass m_playing3DSoundsCS;
321+
CriticalSectionClass m_playingStreamsCS;
322+
CriticalSectionClass m_fadingAudioCS;
323+
310324
AudioFileCache *m_audioCache;
311325
PlayingAudio *m_binkHandle;
312326
UnsignedInt m_num2DSamples;

0 commit comments

Comments
 (0)