Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: Audio causes hang within FreeLibrary.  (Read 5511 times)

0 Members and 1 Guest are viewing this topic.

devlin

  • Full Member
  • ***
  • Posts: 128
    • View Profile
Audio causes hang within FreeLibrary.
« on: January 29, 2011, 08:12:25 pm »
Greetings!

I'm having problems with Audio when playing sound via a DLL plugin.

Basically, my current project loads game views from DLLs as a plugin system. If I load and play any sound/music from within that DLL - the application will hang upon FreeLibrary of that DLL and the music will stutter (no doubt due to the hang/deadlock).

I can get rid of the stutter by sleeping a few milliseconds after the Music.Stop() - before I unload the plugin via FreeLibrary. However, the application will still hang upon FreeLibrary.

I've tried to not allocate anything regarding music from within the DLL itself (rather letting the main-process load and play stuff) but that does not help. FreeLibrary seem to run in a recursive loop upon calling FreeLibrary.

Pseudocode (as a minimal example would involve 2 different projects etc - can provide if needed):

DLL:
Code: [Select]
plugin::init()
{
  sf::Music myMusic;
  myMusic.LoadFromFile("snd.ogg");  // if I comment out this and the line below - FreeLibrary doesn't hang.
  myMusic.Play();
}

plugin::deinit()
{
  myMusic.Stop();                   // seems to call a wait internally? But if I don't add a Sleep here, the sound will stutter when I try to unload the plugin.
}


Main program:
Code: [Select]
Plugin p = LoadPlugin("name.dll"); // creates a view internally
game.AddView(p);                   // adds the view to the game, calls init on plugin
game.MainLoop();                   // calls deinit on the plugin when done, does not unload the plugin but deletes the internal view.
p.Unload();                        // tries to unload the plugin via freelibrary - hangs upon the call to FreeLibrary.


Any idea whatsoever what might cause this? Is there anything allocated internally

JAssange

  • Full Member
  • ***
  • Posts: 104
    • View Profile
Audio causes hang within FreeLibrary.
« Reply #1 on: January 30, 2011, 12:16:16 am »
If SFML uses GetModuleHandle for loading the DLL then when your plugin calls FreeLibrary the reference count becomes 0 and unloads from the process as GetModuleHandle doesn't increment it.

devlin

  • Full Member
  • ***
  • Posts: 128
    • View Profile
Audio causes hang within FreeLibrary.
« Reply #2 on: January 30, 2011, 09:23:17 am »
SFML isn't involved in loading the plugin - that's my own code completely. (using loadlibrary, not getmodulehandle).

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Audio causes hang within FreeLibrary.
« Reply #3 on: January 30, 2011, 10:19:26 am »
Could you provide a minimal and complete example that reproduces the problem?
Laurent Gomila - SFML developer

devlin

  • Full Member
  • ***
  • Posts: 128
    • View Profile
Audio causes hang within FreeLibrary.
« Reply #4 on: January 30, 2011, 01:33:37 pm »
Windows only - I'm afraid.

If you comment out the "StopMusic" at the end, the sound will loop-stutter indefinately. (obviously) - but whether you comment that out or not, the process will still hang. (check task manager)

This below is not really how things look in my code - it's just an example that reproduces the problem. All error checking have been stripped for readability. Please note that I could very well be doing something stupidly wrong - but it doesn't feel like it.

Minimal code for DLL:
Code: [Select]
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <string>
#define DLL extern "C" __declspec(dllexport)

#define SFML_STATIC
#include <SFML/Audio.hpp>
#pragma comment(lib, "sfml-audio-s.lib")
#pragma comment(lib, "sfml-system-s.lib")

BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved )
{
return TRUE;
}

DLL sf::Music * PlayMusic(std::string filename)
{
sf::Music * m = new sf::Music;
m->OpenFromFile(filename);
m->Play();

return m;
}

DLL void StopMusic(sf::Music *m)
{
m->Stop();
delete m; m=0;
}


And for the executable:
Code: [Select]
#define SFML_STATIC
#include <SFML/Audio.hpp>

#define WIN32_LEAN_AND_MEAN
#include <Windows.h>

// plugin stuff, platform independant usually but trimmed down here.
#define PLUGIN_LOAD(a)          LoadLibraryA(a)
#define PLUGIN_GETSYM(a, b)     GetProcAddress(a, b)
#define PLUGIN_UNLOAD(a)        FreeLibrary(a)
#define PLUGIN_HANDLE HMODULE
#if !defined(HMODULE)
struct HINSTANCE__;
typedef struct HINSTANCE__* HMODULE;
#endif

#pragma comment(lib, "sfml-audio-s.lib")
#pragma comment(lib, "sfml-system-s.lib")
#pragma comment(lib, "sfml-main.lib")

int main()
{
// load the DLL
PLUGIN_HANDLE p = PLUGIN_LOAD("crashDLL.dll");
void * playMusic_f = PLUGIN_GETSYM(p, "PlayMusic");
void * stopMusic_f = PLUGIN_GETSYM(p, "StopMusic");

// function pointers
sf::Music *(*PlayMusic)(std::string);
void (*StopMusic)(sf::Music *);
PlayMusic = reinterpret_cast<sf::Music *(*)(std::string)>(playMusic_f);
StopMusic = reinterpret_cast<void (*)(sf::Music *)>(stopMusic_f);

// So far so good!
sf::Music * m = PlayMusic("music.ogg");

MessageBoxA(NULL, "There will be a crash in your imminent future!", "Nostradamus 2011", MB_OK);

StopMusic(m);
PLUGIN_UNLOAD(p);          // crashes here, seem to be some sort of deadlock.

return EXIT_SUCCESS;
}


Put the DLL and a music file named "music.ogg" into the same directory as the executable, along with libsndfile-1.dll and openal.dll to test.

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Audio causes hang within FreeLibrary.
« Reply #5 on: January 30, 2011, 05:56:15 pm »
Quote
Windows only - I'm afraid.

Windows/VC++ only is perfect for me ;)

I'll try this as soon as I can, thanks.
Laurent Gomila - SFML developer

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Audio causes hang within FreeLibrary.
« Reply #6 on: February 05, 2011, 01:20:07 pm »
You statically link to sfml-audio twice, thus you end up with two copies of the module (one in your DLL, one in your application). Does it help if you link to the dynamic version (and thus avoid duplicating the module)?
Laurent Gomila - SFML developer

devlin

  • Full Member
  • ***
  • Posts: 128
    • View Profile
Audio causes hang within FreeLibrary.
« Reply #7 on: February 05, 2011, 02:01:02 pm »
I will attempt this, thanks.

devlin

  • Full Member
  • ***
  • Posts: 128
    • View Profile
Audio causes hang within FreeLibrary.
« Reply #8 on: February 05, 2011, 03:33:41 pm »
I have now tested using the DLL-route instead, and while this works - it takes a full 8 seconds for the application to exit after unloading the library. (using same code as above, apart from linking to the DLL-libs and not the static ones.)

It also "clutters" the executable directory with a rather large amount of DLLs at the moment. Yes, I'm being pedantic. :)

Is this the only way? :)

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Audio causes hang within FreeLibrary.
« Reply #9 on: February 05, 2011, 03:39:32 pm »
Can you send me your projects (VC2008?) so that I can test them?
Laurent Gomila - SFML developer

devlin

  • Full Member
  • ***
  • Posts: 128
    • View Profile
Audio causes hang within FreeLibrary.
« Reply #10 on: February 05, 2011, 05:52:26 pm »
I'll see if I still have vs2008 installed. Using 2010 myself. :)

Edit: PM sent.

devlin

  • Full Member
  • ***
  • Posts: 128
    • View Profile
Audio causes hang within FreeLibrary.
« Reply #11 on: February 11, 2011, 08:47:13 pm »
A small update, I tried slimming the minimal example down even more. As it turns out, you can change PlayMusic in crashDLL into this:

Code: [Select]
DLL sf::Music * PlayMusic(std::string filename)
{
sf::Music * m = new sf::Music;
return m;
}


And even if you do delete of the received pointer right before FreeLibrary (whether from crashApp or within crashDLL) - it'll hang upon FreeLibrary.

This is without loading any music file, playing, stopping whatsoever. Just allocating the memory and freeing it again. This puts the culprit - in my eyes - somewhere among the music ctor/dtor or in one of the inherited ones.

Do note that if I replace the above with using char-pointers and allocating say 256-byte instead of a sf::Music, the code will work just fine and FreeLibrary won't hang.

devlin

  • Full Member
  • ***
  • Posts: 128
    • View Profile
Audio causes hang within FreeLibrary.
« Reply #12 on: February 11, 2011, 09:18:41 pm »
It seems to be hanging inside:

>   crashDLL.dll!sf::priv::AudioDevice::~AudioDevice()  Line 81 + 0xe bytes   C++

Here, in-fact: alcDestroyContext(audioContext);

I'll do some more digging.

devlin

  • Full Member
  • ***
  • Posts: 128
    • View Profile
Audio causes hang within FreeLibrary.
« Reply #13 on: February 11, 2011, 10:05:38 pm »
It seems the culprit is around: (ALCheck.cpp)
Code: [Select]
void EnsureALInit()
{
    // The audio device is instanciated on demand rather than at global startup,
    // which solves a lot of weird crashes and errors.
    // It is destroyed at global exit which is fine.

    //static AudioDevice globalDevice;
}

The static is usually not commented - but I did the above and put:

sf::priv::AudioDevice globalDevice;

inside my main function instead - and everything works as it should. (even when using static linking)