From b812f1cdbdd266c770423017f47a129e64811cf0 Mon Sep 17 00:00:00 2001 From: havoc Date: Mon, 23 May 2011 09:41:52 +0000 Subject: [PATCH] fix a crash in debug builds where the compiler did not optimize ch->sfx-> to use a local variable holding the unchanging value of sfx (the crash occurs when the mixer thread clears ch->sfx while the main thread is deciding whether to merge a sound onto an existing channel - if the channel dies during this code, the sfx pointer must be preserved) git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@11161 d7cf8633-e32d-0410-b094-e92efae38249 --- snd_main.c | 12 ++++++++---- snd_main.h | 2 +- snd_mix.c | 9 +++++++-- 3 files changed, 16 insertions(+), 7 deletions(-) diff --git a/snd_main.c b/snd_main.c index fac45a4f..9265cb68 100644 --- a/snd_main.c +++ b/snd_main.c @@ -1200,6 +1200,7 @@ channel_t *SND_PickChannel(int entnum, int entchannel) int first_to_die; int first_life_left, life_left; channel_t* ch; + sfx_t *sfx; // use this instead of ch->sfx->, because that is volatile. // Check for replacement sound, or find the best one to replace first_to_die = -1; @@ -1224,7 +1225,8 @@ channel_t *SND_PickChannel(int entnum, int entchannel) for (ch_idx=NUM_AMBIENTS ; ch_idx < NUM_AMBIENTS + MAX_DYNAMIC_CHANNELS ; ch_idx++) { ch = &channels[ch_idx]; - if (!ch->sfx) + sfx = ch->sfx; // fetch the volatile variable + if (!sfx) { // no sound on this channel first_to_die = ch_idx; @@ -1236,9 +1238,9 @@ channel_t *SND_PickChannel(int entnum, int entchannel) continue; // don't override looped sounds - if ((ch->flags & CHANNELFLAG_FORCELOOP) || ch->sfx->loopstart < ch->sfx->total_length) + if ((ch->flags & CHANNELFLAG_FORCELOOP) || sfx->loopstart < sfx->total_length) continue; - life_left = ch->sfx->total_length - ch->pos; + life_left = sfx->total_length - ch->pos; if (life_left < first_life_left) { @@ -1852,6 +1854,7 @@ void S_UpdateAmbientSounds (void) int ambient_channel; channel_t *chan; unsigned char ambientlevels[NUM_AMBIENTS]; + sfx_t *sfx; memset(ambientlevels, 0, sizeof(ambientlevels)); if (cl.worldmodel && cl.worldmodel->brush.AmbientSoundLevelsForPoint) @@ -1861,7 +1864,8 @@ void S_UpdateAmbientSounds (void) for (ambient_channel = 0 ; ambient_channel< NUM_AMBIENTS ; ambient_channel++) { chan = &channels[ambient_channel]; - if (chan->sfx == NULL || chan->sfx->fetcher == NULL) + sfx = chan->sfx; // fetch the volatile variable + if (sfx == NULL || sfx->fetcher == NULL) continue; vol = (int)ambientlevels[ambient_channel]; diff --git a/snd_main.h b/snd_main.h index c7c631f8..7419e9ce 100644 --- a/snd_main.h +++ b/snd_main.h @@ -86,7 +86,7 @@ typedef struct channel_s { int listener_volume [SND_LISTENERS]; // 0-65536 volume per speaker int master_vol; // 0-65536 master volume - sfx_t *sfx; // sfx number + sfx_t *sfx; // pointer to sound sample being used unsigned int flags; // cf CHANNELFLAG_* defines int pos; // sample position in sfx, negative values delay the start of the sound playback int entnum; // to allow overriding a specific sound diff --git a/snd_mix.c b/snd_mix.c index 05abc83a..cc425bac 100644 --- a/snd_mix.c +++ b/snd_mix.c @@ -186,6 +186,11 @@ static qboolean SND_PaintChannel (channel_t *ch, portable_sampleframe_t *paint, int vol[SND_LISTENERS]; const snd_buffer_t *sb; unsigned int i, sb_offset; + sfx_t *sfx; + + sfx = ch->sfx; // fetch the volatile variable + if (!sfx) // given that this is called by the mixer thread, this never happens, but... + return false; // move to the stack (do we need to?) for (i = 0;i < SND_LISTENERS;i++) @@ -199,11 +204,11 @@ static qboolean SND_PaintChannel (channel_t *ch, portable_sampleframe_t *paint, return false; sb_offset = ch->pos; - sb = ch->sfx->fetcher->getsb (ch->sfx->fetcher_data, &ch->fetcher_data, &sb_offset, count); + sb = sfx->fetcher->getsb (sfx->fetcher_data, &ch->fetcher_data, &sb_offset, count); if (sb == NULL) { Con_DPrintf("SND_PaintChannel: ERROR: can't get sound buffer from sfx \"%s\"\n", - ch->sfx->name); // , count); // or add this? FIXME + sfx->name); // , count); // or add this? FIXME return false; } else -- 2.39.2