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

FlexASIO entry points are not thread safe #185

Open
dechamps opened this issue Feb 4, 2023 · 2 comments
Open

FlexASIO entry points are not thread safe #185

dechamps opened this issue Feb 4, 2023 · 2 comments

Comments

@dechamps
Copy link
Owner

dechamps commented Feb 4, 2023

Currently FlexASIO driver methods are not guaranteed to be thread safe. For example, attempting to call getLatencies() and createBuffers() at the same time will trigger undefined behaviour. More worryingly, concurrent canSampleRate() calls will result in concurrent PortAudio calls, which is unlikely to end well as PortAudio itself is not thread safe (in fact, it's downright thread-hostile - see #124).

The reason why FlexASIO assumes its entry points will not be called concurrently is because I was under the assumption that this would not be allowed under the ASIO SDK, but after a closer examination in the context of eiz/SynchronousAudioRouter#133, it turns out that this is not as clear as I originally assumed - the ASIO SDK expresses no opinion one way or the other. Therefore, the robustness principle would dictate that drivers should be resilient to concurrent calls.

I don't remember seeing a log from any FlexASIO user where the host made concurrent calls, so thankfully this concern seems mostly academic at this point.

One way to fix this could be to wrap all driver calls under a mutex, or maybe we can address #124 at the same time by scheduling all calls into a single dedicated thread.

@dechamps
Copy link
Owner Author

dechamps commented Feb 4, 2023

Implementation note: we'll need to be careful around ASIO callbacks such as asioMessage. Specifically, we'll want to ensure we don't deadlock if the ASIO host attempts to reenter the driver from inside the callback.

@dechamps
Copy link
Owner Author

Actually I can see some symptoms of this when REW closes FlexASIO:

2024-05-26T22:33:50.3272332+01:00 128180 194716 --- EXITING CONTEXT: ~CFlexASIO() [OK]
2024-05-26T22:33:50.3272424+01:00 128180 194716 Terminating PortAudio
2024-05-26T22:33:50.3272543+01:00 128180 194716 [PortAudio] TerminateHostApis in
2024-05-26T22:33:50.3273287+01:00 128180 194716 [PortAudio] ERROR: failed PaWinUtil_CoUninitialize calling thread[194716] does not match initializing thread[183640]
2024-05-26T22:33:50.3273536+01:00 128180 194716 [PortAudio] ERROR: failed PaWinUtil_CoUninitialize calling thread[194716] does not match initializing thread[183640]
2024-05-26T22:33:50.3273724+01:00 128180 194716 [PortAudio] TerminateHostApis out
2024-05-26T22:33:50.3273812+01:00 128180 194716 PortAudio terminated successfully

Fortunately this particular case doesn't seem to cause user-visible issues.

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

No branches or pull requests

1 participant