Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

sf::AudioDevice: Manual shutdown / destruction #273

Closed
pdinklag opened this issue Aug 21, 2012 · 7 comments
Closed

sf::AudioDevice: Manual shutdown / destruction #273

pdinklag opened this issue Aug 21, 2012 · 7 comments

Comments

@pdinklag
Copy link

I am opening this issue to make sure this is not forgotten. It is not really related to #30, because I do not experience any crashes. The problem I experience is described in this forum post, but there might as well be other uses for this.

The sf::AudioDevice is currently destroyed at application exit, however, a manual shut down might be required before that. In my particular case, I have no control over the app exit and the sf::AudioDevice destructor is never invoked, leaving the OpenAL thread running. The only way to get rid of it is killing the application manually.

There should be a way to manually force the destruction of the audio device.

@LaurentGomila
Copy link
Member

It is somehow related to #30 because the solution to it will most likely solve your problem too.

The destructor of sf::AudioDevice is currently called when the SFML DLL is unloaded. So this has to happen if your java program ends properly, I can't find any good reason for the JVM to not unload the DLLs that the program uses. At worst, it is done at the very end of the execution, but it is done anyway. Why wouldn't it be so?

@pdinklag
Copy link
Author

The JVM exit never happens. I have a feeling that the JVM waits for all threads to end or tries to stop them and can't, maybe because it didn't create the OpenAL thread by itself. I'm really not exactly sure what is going on. I will try to get a better insight using jstacklater.

You can force all threads to be killed using System.exit(0), but Sun recommends to do this only in severe error cases or if your application is merely a utility script where the exit code matters. In any event, this seems to be a workaround which I will recommend when using sound streams.

In a demo project I work on I use sounds (sf::Sound). Do they also use a dedicated audio thread? Because the issue never occured in that project so far.

@LaurentGomila
Copy link
Member

The JVM exit never happens.

To me, this is the actual problem. A function called at global exit in C++ is totally valid and should not prevent things from exiting properly, except in case of conflict between other globals. But that's unlikely to be the case here.

Did you try to add a function to manually destroy the sf::AudioDevice instance? Does it solve the problem?

I have a feeling that the JVM waits for all threads to end or tries to stop them and can't, maybe because it didn't create the OpenAL thread by itself.

I don't know how OpenAL threads are managed, so I can't help. But it could be part of the problem.

In a demo project I work on I use sounds (sf::Sound). Do they also use a dedicated audio thread?

Every sound source use a thread, the caller thread is never blocked when something is played.

@pdinklag
Copy link
Author

The JVM exit never happens.

To me, this is the actual problem. A function called at global exit in C++ is totally valid and should not prevent things from exiting properly, except in case of conflict between other globals. But that's unlikely to be the case here.

This all happens only if a sound stream was played. If I never play a sound stream, the JVM exits properly and all exit hooks get called.

So yes, I agree, this is the actual problem, but we cannot influence the OpenAL or JVM thread management directly. Maybe attaching the OpenAL thread to the JVM could help, but I doubt that I can get custom code executed in the OpenAL thread?

Did you try to add a function to manually destroy the sf::AudioDevice instance? Does it solve the problem?

I tried this back when I first reported the issue on the forum and it did solve the problem. It seems that either destroying the context or closing the device (both actions are done in the sf::AudioDevice destructor) also terminates the OpenAL thread.

I don't know how OpenAL threads are managed, so I can't help.

At least it seems certain that it is terminated when the audio device is destroyed, which is exactly what I need.

Every sound source use a thread, the caller thread is never blocked when something is played.

I take it that they all use the OpenAL thread (alSourcePlay probably triggers that)? And streams additionally use a thread to queue buffers - but these do not seem to be causing any trouble.

This is a little odd, because I only experienced the whole issue with sound streams so far. Maybe this is where to start looking. The only real difference I see is that sf::SoundStream uses buffer queues, maybe that's somehow related.


The System.exit thing might be an acceptable solution for now, although it is generally not recommended.
After thinking this over again, even if you can shut down the audio device manually, either I'd have to do that in a shutdown hook (which never gets called), or users would have to do that by themselves - and then they can just as well use System.exit.

@pdinklag
Copy link
Author

OK, this just became more interesting: it does not happen with sf::Music either. I'll try find out why...

@pdinklag
Copy link
Author

Issue solved!
Strictly speaking, this is a case of RTFM... however, I have the excuse that the JNI (Java Native Interface) is badly documented.

Anyway, in my custom sf::SoundStream implementation in onSeek and onGetData, I need to obtain a so-called JNI environment, because I need to call Java methods (so Java implementations of sound streams become possible). Doing so attaches the thread that calls it - in this case the stream's m_thread - to the JVM, and what I did not do is detach it. That resulted in this problem.

Now I detach the thread from the JVM after I'm done calling Java methods - and the issue is fixed!
Sorry for making this an issue and blaming it on SFML.

@LaurentGomila
Copy link
Member

Great :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants