Support 'atexit'-based cleanup on Windows #849
Closed
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Hello!
We have started using
miniaudio
in SFML 3.x and so far our experience has been great.As an attempt to simplify our audio resource management, I attempted to remove run-time based reference counting in lieu of a simpler manager object with a
static
lifetime -- an important first step towards adding support for multiple audio devices in our library (see SFML/SFML#2974).My changes unfortunately ended up causing problems on Windows, as any application using our audio module freezes on termination. After some investigation by @binary1248 and some further tests by myself we realized that the problem is due to how Windows handles
atexit
and thread termination when building as a shared library.Basically, as part of process termination procedure, the Win32 runtime will forcefully terminate any remaining thread without joining them nor sending a thread-detach notification. This means that anybody trying to cleanup
miniaudio
resources viaatexit
(which is exactly how C++'sstatic
object destructors are invoked) will end up with a program hanging onma_event_wait(&pDevice->stopEvent)
insidema_engine_uninit
, becausepDevice->thread
was terminated and there was never a chance to signal the stop event.A simple workaround for this issue is to check if the thread is still alive prior to waiting on
stopEvent
. I've done some research and found this solution that suggests it's sufficient to checkWaitForSingleObject(threadHandle, 0) == WAIT_TIMEOUT
to see if the thread is still alive.Applying the changes to
miniaudio.h
and trying them out under our SFML test suite both as a static and as a shared library seems to resolve the issue and support our use case.As an added benefit, any C or C++ developer using
atexit
forminiaudio
cleanup will benefit from this change, and any other C++ developer usingstatic
lifetime forminiaudio
cleanup will also do so.Thanks!