(A5) random crash on al_detach_voice()
thebignic

Using Allegro 5.0.5 running on Win XP, Directx9.0c I'm encountering an intermittent lockup when cleaning up audio.

Under Win7, I haven't encountered the bug at all.

If I destroy the mixer before destroying my voice, sometimes the program will lock at al_destroy_mixer.

If I destroy the voice first, it will hang on al_detach_voice(voice).

Once in a while it will get passed al_destroy_voice, al_destroy_mixer() and then hang on al_uninstall_audio().

This may be a huge assumption, but will al_destroy_mixer detach any attached voices before it is cleaned up? Will al_uninstall_audio() also attempt to do the same thing? WHAT IS THE PROPER ORDER?

When I say intermittent, I mean sometimes it will run/exit fine 20 times in a row (just loading main screen, exiting) and then randomly crash. Only thing I can do to reproduce it is to keep running/exiting until it happens. Code:blocks debugger doesnt appear to even catch that the app is hung up?

#SelectExpand
1 2 audio cleanup routine 3 ... 4 5 6 7 al_stop_samples(); 8 9 10 if (stream) { 11 std::cout << "destroying stream...\n"; 12 13 al_set_audio_stream_playing(stream, false); 14 al_unregister_event_source(event_queue, al_get_audio_stream_event_source(stream)); 15 16 17 al_detach_audio_stream(stream); 18 al_destroy_audio_stream(stream); 19 } 20 if (menuStream) { 21 std::cout << "destroying menuStream...\n"; 22 23 al_set_audio_stream_playing(menuStream, false); 24 al_unregister_event_source(event_queue, al_get_audio_stream_event_source(menuStream)); 25 26 al_detach_audio_stream(menuStream); 27 al_destroy_audio_stream(menuStream); 28 } 29 30 if (mixer) { 31 std::cout << "al_destroy_mixer...\n"; 32 al_destroy_mixer(mixer); 33 } 34 35 if (voice) { 36 std::cout << "al_set_voice_playing(voice, false)...\n"; 37 al_set_voice_playing(voice, false); 38 std::cout << "al_detach_voice(voice);...\n"; 39 al_detach_voice(voice); 40 std::cout << "al_destroy_voice(voice);...\n"; 41 al_destroy_voice(voice); 42 } 43 44 45 46 if (al_is_audio_installed) { 47 std::cout << "al_uninstall_audio...\n"; 48 al_uninstall_audio(); 49 }

I can't really post complete code due to the size of the project and the resources involved. Just wanted to know if anyone else has had intermittent issues with cleaning up audio, and if so, what might I be doing wrong?

In that code, I am setting the streams to stop regardless of their state since if al_get_audio_stream_playing(stream) was returning false even though the stream WAS playing. Curious...

I generally don't post threads, preferring to smash my head against the wall and look at other forum posts until I've fixed the issue but I've searched high and low for similar issues and of the two threads I've seen, both seem to be unanswered.

Help me Obi Wan Allegro.cc... you're my only hope!

Edit: Debug did catch a crash finally...

#0 00000000 0x00448574 in _dsound_stop_voice() (??:??)
#1 00000000 0x00442f84 in al_detach_voice() (??:??)
#2 00000000 0x004467bf in _al_kcm_destroy_sample() (??:??)
#3 00000000 0x004445d6 in al_destroy_mixer() (??:??)
#4 00000000 0x00442930 in _al_kcm_shutdown_default_mixer() (??:??)
#5 00000000 0x00441e28 in al_uninstall_audio() (??:??)
#6 00000000 0x00467d1d in _al_run_exit_funcs() (??:??)
#7 00000000 0x00462ee8 in al_uninstall_system() (??:??)
#8 77C39E24 msvcrt!_initterm() (C:\WINNT\system32\msvcrt.dll:??)
#9 77C39EC5 msvcrt!_cexit() (C:\WINNT\system32\msvcrt.dll:??)
#10 00000000 0x00000000 in ??() (??:??)

EDIT - Updated Code:
Rather than crashing on al_detach_voice(); this code generally crashes on al_detach_mixer() unless I check al_get_mixer_attached(mixer). If I check, it seems to be false, and thus doesnt detach and it will crash on al_destroy_mixer()

I can't see anything in allegro.log that appears to be of relevance...

#SelectExpand
1 2 if (stream) { 3 std::cout << "destroying stream...\n"; 4 al_drain_audio_stream(stream); 5 al_set_audio_stream_playing(stream, false); 6 al_unregister_event_source(event_queue, al_get_audio_stream_event_source(stream)); 7 8 9 if (al_get_audio_stream_attached(stream)) { al_detach_audio_stream(stream); } 10 al_destroy_audio_stream(stream); 11 } 12 13 if (menuStream) { 14 std::cout << "destroying menuStream...\n"; 15 16 al_drain_audio_stream(menuStream); 17 18 al_set_audio_stream_playing(menuStream, false); 19 al_unregister_event_source(event_queue, al_get_audio_stream_event_source(menuStream)); 20 21 22 if (al_get_audio_stream_attached(menuStream)) { al_detach_audio_stream(menuStream); } 23 al_destroy_audio_stream(menuStream); 24 } 25 26 //#ifndef BYPASS_MIXER 27 if (mixer) { 28 29 if (al_get_mixer_attached(mixer)) { 30 std::cout << "al_detach_mixer...\n"; 31 al_detach_mixer(mixer); 32 } 33 34 std::cout << "al_destroy_mixer...\n"; 35 al_destroy_mixer(mixer); 36 } 37 //#endif 38 39 if (voice) { 40 std::cout << "al_detach_voice(voice);...\n"; 41 al_detach_voice(voice); 42 std::cout << "al_destroy_voice(voice);...\n"; 43 al_destroy_voice(voice); 44 } 45 46 47 if (al_is_audio_installed) { 48 std::cout << "al_uninstall_audio...\n"; 49 al_uninstall_audio(); 50 }

Tearing my hair out of my skull now... Why is it so random? Why do I have to run it 20-30 times before it'll happen? Then sometimes it'll happen as soon as I build and run once....

SiegeLord

Could you try running this with a) 5.0.7 and b) with debug symbols turned on (so we see the lines in the backtrace)?

Anyway, the order you're doing things seems to be right, as this is the order Allegro uses for its default mixer:

al_destroy_mixer(allegro_mixer);
al_destroy_voice(allegro_voice);

thebignic

Linking to 5.0.7 now... Same issue.
Not sure why the debug trace shows up as allegro-5.0.x?

#0 0045002C _dsound_stop_voice(voice=0x1b130c0) (D:\Libraries\build\allegro\src\allegro-5.0.x\allegro-5.0.x\addons\audio\dsound.cpp:460)
#1 0044545A al_detach_voice(voice=0x1b130c0) (D:\Libraries\build\allegro\src\allegro-5.0.x\allegro-5.0.x\addons\audio\kcm_voice.c:376)
#2 0044A5C3 _al_kcm_detach_from_parent(spl=0x1b13738) (D:\Libraries\build\allegro\src\allegro-5.0.x\allegro-5.0.x\addons\audio\kcm_instance.c:116)
#3 0044A86D _al_kcm_destroy_sample(spl=0x1b13738, unregister=false) (D:\Libraries\build\allegro\src\allegro-5.0.x\allegro-5.0.x\addons\audio\kcm_instance.c:205)
#4 00448CDD al_destroy_mixer(mixer=0x1b13738) (D:\Libraries\build\allegro\src\allegro-5.0.x\allegro-5.0.x\addons\audio\kcm_mixer.c:943)
#5 00444585 _al_kcm_shutdown_default_mixer() (D:\Libraries\build\allegro\src\allegro-5.0.x\allegro-5.0.x\addons\audio\kcm_sample.c:476)
#6 0044358A al_uninstall_audio() (D:\Libraries\build\allegro\src\allegro-5.0.x\allegro-5.0.x\addons\audio\audio.c:323)
#7 004AF399 _al_run_exit_funcs() (D:\Libraries\build\allegro\src\allegro-5.0.x\allegro-5.0.x\src\allegro.c:136)
#8 004A8C5B al_uninstall_system() (D:\Libraries\build\allegro\src\allegro-5.0.x\allegro-5.0.x\src\system.c:310)
#9 77C39E24 msvcrt!_initterm() (C:\WINNT\system32\msvcrt.dll:??)
#10 77C39EC5 msvcrt!_cexit() (C:\WINNT\system32\msvcrt.dll:??)
#11 00000000 0x00000000 in ??() (??:??)

From dsound.cpp...
Line 460 is the last error... could this be failing because the buffer is already released? Shouldn't we check if its still valid before releasing? I've never compiled allegro on my own... not looking forward to the prospect of it, or the prospect of debugging directX having NO experience with it...

#SelectExpand
437/* The stop_voice method should stop playback. For non-streaming voices, it 438 should leave the data loaded, and reset the voice position to 0. */ 439static int _dsound_stop_voice(ALLEGRO_VOICE* voice) 440{ 441 ALLEGRO_DS_DATA *ex_data = (ALLEGRO_DS_DATA *)voice->extra; 442 443 if (!ex_data->ds8_buffer) { 444 ALLEGRO_ERROR("Trying to stop empty voice buffer\n"); 445 return 1; 446 } 447 448 /* if playing a sample */ 449 if (!voice->is_streaming) { 450 ex_data->ds8_buffer->Stop(); 451 return 0; 452 } 453 454 if (ex_data->stop_voice == 0) { 455 ex_data->stop_voice = 1; 456 al_join_thread(ex_data->thread, NULL); 457 al_destroy_thread(ex_data->thread); 458 } 459 460 ex_data->ds8_buffer->Release(); 461 ex_data->ds8_buffer = NULL; 462 463 return 0; 464}

Also in dsound.cpp... Not sure if/when this is called (perhaps completely unrelated) Is the buffer intentionally not NULLed? Shouldnt it be?

#SelectExpand
375/* The unload_voice method unloads a sample previously loaded with load_voice. 376 This method should not be called on a streaming voice. */ 377static void _dsound_unload_voice(ALLEGRO_VOICE *voice) 378{ 379 ALLEGRO_DS_DATA *ex_data = (ALLEGRO_DS_DATA *)voice->extra; 380 ex_data->ds8_buffer->Release(); 381}

SiegeLord

Where do you get your voice/mixer from? It's not the allegro's default voice/mixer by any chance, is it?

thebignic

Not sure what the "default mixer" would be? This is the initial setup

#SelectExpand
1 if(!al_install_audio()){ 2 fprintf(stderr, "failed to initialize audio!\n"); 3 return -1; 4 } 5 6std::cout << " initialized audio\n"; 7 8 if(!al_init_acodec_addon()){ 9 fprintf(stderr, "failed to initialize audio codecs!\n"); 10 return -1; 11 } 12 13std::cout << " initialized al_init_acodec_addon()\n"; 14 15 16 if (!al_reserve_samples(16)){ 17 fprintf(stderr, "failed to reserve samples!\n"); 18 return -1; 19 } 20 21 voice = al_create_voice(44100, ALLEGRO_AUDIO_DEPTH_INT16, ALLEGRO_CHANNEL_CONF_2); 22 if (!voice) { 23 fprintf(stderr, "Could not create ALLEGRO_VOICE.\n"); 24 return -1; 25 } 26 27 mixer = al_create_mixer(44100, ALLEGRO_AUDIO_DEPTH_FLOAT32, ALLEGRO_CHANNEL_CONF_2); 28 if (!mixer) { 29 fprintf(stderr, "Could not create ALLEGRO_MIXER.\n"); 30 return 1; 31 } 32 33 if (!al_attach_mixer_to_voice(mixer, voice)) { 34 fprintf(stderr, "al_attach_mixer_to_voice failed.\n"); 35 return 1; 36 } 37 38 39 initialized=true;

Elias

al_reserve_samples already will create a voice and mixer for you (and attach it), so you don't need the last three calls at all.

It still sounds like there is a bug in Allegro as creating a second voice is supposed to work. But a quick fix is likely to either not call al_reserve_samples (and don't use al_play_sample) or don't create a second voice.

thebignic

Remarked out all the voice and mixer code, and attached my streams to the default mixer via al_get_default_mixer().

Seemed to work for a while (about thirty runs) but crashed again, this time on al_uninstall_audio(); Still crashed on the same line though....

#0 0044ED30 _dsound_stop_voice(voice=0x1b13868) (D:\Libraries\build\allegro\src\allegro-5.0.x\allegro-5.0.x\addons\audio\dsound.cpp:460)
#1 0044FDDA al_detach_voice(voice=0x1b13868) (D:\Libraries\build\allegro\src\allegro-5.0.x\allegro-5.0.x\addons\audio\kcm_voice.c:376)
#2 0044536F _al_kcm_detach_from_parent(spl=0x121c58e0) (D:\Libraries\build\allegro\src\allegro-5.0.x\allegro-5.0.x\addons\audio\kcm_instance.c:116)
#3 00445619 _al_kcm_destroy_sample(spl=0x121c58e0, unregister=false) (D:\Libraries\build\allegro\src\allegro-5.0.x\allegro-5.0.x\addons\audio\kcm_instance.c:205)
#4 0044B419 al_destroy_mixer(mixer=0x121c58e0) (D:\Libraries\build\allegro\src\allegro-5.0.x\allegro-5.0.x\addons\audio\kcm_mixer.c:943)
#5 00444751 _al_kcm_shutdown_default_mixer() (D:\Libraries\build\allegro\src\allegro-5.0.x\allegro-5.0.x\addons\audio\kcm_sample.c:476)
#6 00443756 al_uninstall_audio() (D:\Libraries\build\allegro\src\allegro-5.0.x\allegro-5.0.x\addons\audio\audio.c:323)
#7 004AF565 _al_run_exit_funcs() (D:\Libraries\build\allegro\src\allegro-5.0.x\allegro-5.0.x\src\allegro.c:136)
#8 004A8E27 al_uninstall_system() (D:\Libraries\build\allegro\src\allegro-5.0.x\allegro-5.0.x\src\system.c:310)
#9 77C39E24 msvcrt!_initterm() (C:\WINNT\system32\msvcrt.dll:??)
#10 77C39EC5 msvcrt!_cexit() (C:\WINNT\system32\msvcrt.dll:??)
#11 00000000 0x00000000 in ??() (??:??)

I have the most recent audio drivers for the chipset. Allegro.log doesn't appear to have any relevant information and I find that somewhat curious.

Perhaps I should note that the crash seems to occur even if I hadn't actually played any samples or streams yet.

SiegeLord

Does this happen with the Allegro examples, like ex_audio_simple? I tried the examples on WinXP and they never crashed for me.

Thread #610569. Printed from Allegro.cc