Skip to content
Permalink
Browse files

Corrected race condition in positional effects.

  Fixes Bugzilla #651.
  • Loading branch information
icculus committed Oct 11, 2009
1 parent 9b43f36 commit ff457f082f9d85320b478d115acfa8ff37f3729c
Showing with 75 additions and 26 deletions.
  1. +40 −15 effect_position.c
  2. +6 −0 effects_internal.h
  3. +29 −11 mixer.c
@@ -1427,6 +1427,8 @@ int Mix_SetPanning(int channel, Uint8 left, Uint8 right)
int channels;
Uint16 format;
position_args *args = NULL;
int retval = 1;

Mix_QuerySpec(NULL, &format, &channels);

if (channels != 2 && channels != 4 && channels != 6) /* it's a no-op; we call that successful. */
@@ -1449,16 +1451,22 @@ int Mix_SetPanning(int channel, Uint8 left, Uint8 right)
if (f == NULL)
return(0);

SDL_LockAudio();
args = get_position_arg(channel);
if (!args)
if (!args) {
SDL_UnlockAudio();
return(0);
}

/* it's a no-op; unregister the effect, if it's registered. */
if ((args->distance_u8 == 255) && (left == 255) && (right == 255)) {
if (args->in_use) {
return(Mix_UnregisterEffect(channel, f));
retval = _Mix_UnregisterEffect_locked(channel, f);
SDL_UnlockAudio();
return(retval);
} else {
return(1);
SDL_UnlockAudio();
return(1);
}
}

@@ -1470,10 +1478,11 @@ int Mix_SetPanning(int channel, Uint8 left, Uint8 right)

if (!args->in_use) {
args->in_use = 1;
return(Mix_RegisterEffect(channel, f, _Eff_PositionDone, (void *) args));
retval=_Mix_RegisterEffect_locked(channel, f, _Eff_PositionDone, (void*)args);
}

return(1);
SDL_UnlockAudio();
return(retval);
}


@@ -1483,23 +1492,30 @@ int Mix_SetDistance(int channel, Uint8 distance)
Uint16 format;
position_args *args = NULL;
int channels;
int retval = 1;

Mix_QuerySpec(NULL, &format, &channels);
f = get_position_effect_func(format, channels);
if (f == NULL)
return(0);

SDL_LockAudio();
args = get_position_arg(channel);
if (!args)
if (!args) {
SDL_UnlockAudio();
return(0);
}

distance = 255 - distance; /* flip it to our scale. */

/* it's a no-op; unregister the effect, if it's registered. */
if ((distance == 255) && (args->left_u8 == 255) && (args->right_u8 == 255)) {
if (args->in_use) {
return(Mix_UnregisterEffect(channel, f));
retval = _Mix_UnregisterEffect_locked(channel, f);
SDL_UnlockAudio();
return(retval);
} else {
SDL_UnlockAudio();
return(1);
}
}
@@ -1508,10 +1524,11 @@ int Mix_SetDistance(int channel, Uint8 distance)
args->distance_f = ((float) distance) / 255.0f;
if (!args->in_use) {
args->in_use = 1;
return(Mix_RegisterEffect(channel, f, _Eff_PositionDone, (void *) args));
retval = _Mix_RegisterEffect_locked(channel, f, _Eff_PositionDone, (void *) args);
}

return(1);
SDL_UnlockAudio();
return(retval);
}


@@ -1522,6 +1539,7 @@ int Mix_SetPosition(int channel, Sint16 angle, Uint8 distance)
int channels;
position_args *args = NULL;
Sint16 room_angle = 0;
int retval = 1;

Mix_QuerySpec(NULL, &format, &channels);
f = get_position_effect_func(format, channels);
@@ -1530,17 +1548,23 @@ int Mix_SetPosition(int channel, Sint16 angle, Uint8 distance)

angle = SDL_abs(angle) % 360; /* make angle between 0 and 359. */

SDL_LockAudio();
args = get_position_arg(channel);
if (!args)
if (!args) {
SDL_UnlockAudio();
return(0);
}

/* it's a no-op; unregister the effect, if it's registered. */
if ((!distance) && (!angle)) {
if (args->in_use) {
return(Mix_UnregisterEffect(channel, f));
retval = _Mix_UnregisterEffect_locked(channel, f);
SDL_UnlockAudio();
return(retval);
} else {
return(1);
}
SDL_UnlockAudio();
return(1);
}
}

if (channels == 2)
@@ -1581,10 +1605,11 @@ int Mix_SetPosition(int channel, Sint16 angle, Uint8 distance)
args->room_angle = room_angle;
if (!args->in_use) {
args->in_use = 1;
return(Mix_RegisterEffect(channel, f, _Eff_PositionDone, (void *) args));
retval = _Mix_RegisterEffect_locked(channel, f, _Eff_PositionDone, (void *) args);
}

return(1);
SDL_UnlockAudio();
return(retval);
}


@@ -45,6 +45,12 @@ void _Mix_InitEffects(void);
void _Mix_DeinitEffects(void);
void _Eff_PositionDeinit(void);

int _Mix_RegisterEffect_locked(int channel, Mix_EffectFunc_t f,
Mix_EffectDone_t d, void *arg);
int _Mix_UnregisterEffect_locked(int channel, Mix_EffectFunc_t f);
int _Mix_UnregisterAllEffects_locked(int channel);


/* Set up for C function definitions, even when using C++ */
#ifdef __cplusplus
}
40 mixer.c
@@ -1276,11 +1276,11 @@ static int _Mix_remove_all_effects(int channel, effect_info **e)
}


int Mix_RegisterEffect(int channel, Mix_EffectFunc_t f,
/* MAKE SURE you hold the audio lock (SDL_LockAudio()) before calling this! */
int _Mix_RegisterEffect_locked(int channel, Mix_EffectFunc_t f,
Mix_EffectDone_t d, void *arg)
{
effect_info **e = NULL;
int retval;

if (channel == MIX_CHANNEL_POST) {
e = &posteffects;
@@ -1292,17 +1292,24 @@ int Mix_RegisterEffect(int channel, Mix_EffectFunc_t f,
e = &mix_channel[channel].effects;
}

return _Mix_register_effect(e, f, d, arg);
}

int Mix_RegisterEffect(int channel, Mix_EffectFunc_t f,
Mix_EffectDone_t d, void *arg)
{
int retval;
SDL_LockAudio();
retval = _Mix_register_effect(e, f, d, arg);
retval = _Mix_RegisterEffect_locked(channel, f, d, arg);
SDL_UnlockAudio();
return(retval);
return retval;
}


int Mix_UnregisterEffect(int channel, Mix_EffectFunc_t f)
/* MAKE SURE you hold the audio lock (SDL_LockAudio()) before calling this! */
int _Mix_UnregisterEffect_locked(int channel, Mix_EffectFunc_t f)
{
effect_info **e = NULL;
int retval;

if (channel == MIX_CHANNEL_POST) {
e = &posteffects;
@@ -1314,17 +1321,22 @@ int Mix_UnregisterEffect(int channel, Mix_EffectFunc_t f)
e = &mix_channel[channel].effects;
}

return _Mix_remove_effect(channel, e, f);
}

int Mix_UnregisterEffect(int channel, Mix_EffectFunc_t f)
{
int retval;
SDL_LockAudio();
retval = _Mix_remove_effect(channel, e, f);
retval = _Mix_UnregisterEffect_locked(channel, f);
SDL_UnlockAudio();
return(retval);
}


int Mix_UnregisterAllEffects(int channel)
/* MAKE SURE you hold the audio lock (SDL_LockAudio()) before calling this! */
int _Mix_UnregisterAllEffects_locked(int channel)
{
effect_info **e = NULL;
int retval;

if (channel == MIX_CHANNEL_POST) {
e = &posteffects;
@@ -1336,8 +1348,14 @@ int Mix_UnregisterAllEffects(int channel)
e = &mix_channel[channel].effects;
}

return _Mix_remove_all_effects(channel, e);
}

int Mix_UnregisterAllEffects(int channel)
{
int retval;
SDL_LockAudio();
retval = _Mix_remove_all_effects(channel, e);
retval = _Mix_UnregisterAllEffects_locked(channel);
SDL_UnlockAudio();
return(retval);
}

0 comments on commit ff457f0

Please sign in to comment.