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

Pa_Initialize(): Guard against recursive calls. #794

Merged
merged 6 commits into from
Apr 4, 2023

Conversation

daschuer
Copy link
Contributor

This fixes a stack overflow when a diver uses portaudio as well like FlexAsio

Fixes: #766

@dechamps
Copy link
Contributor

The proposed code returns paNoError on a recursive call. I don't think that's wise - this situation should never be allowed to occur and it's important to bail out of "undefined behaviour" territory as soon as possible instead of attempting to continue. It would be best to return an error if recursion is detected. (In the case of the FlexASIO-related issue, this will make FlexASIO fail to initialize, which is what we want - FlexASIO should not be allowed to continue with a PortAudio library that is not the one that it came bundled with, as that can cause undefined behaviour and lead to more problems.)

A new error code could be added to the PaErrorCode enum for this case, or if that seems excessive I guess paInternalError could be returned instead.

@daschuer daschuer force-pushed the recursive_initalize branch 2 times, most recently from b34f98c to 2dabaa6 Compare March 15, 2023 00:14
@daschuer
Copy link
Contributor Author

Done

@daschuer daschuer force-pushed the recursive_initalize branch 3 times, most recently from 86a241e to 92625ce Compare March 15, 2023 09:24
src/common/pa_front.c Show resolved Hide resolved
src/common/pa_front.c Show resolved Hide resolved
@daschuer
Copy link
Contributor Author

Done.

@RossBencina RossBencina changed the title Pa_Initalze(): Guard against recursive calls. Pa_Initialze(): Guard against recursive calls. Mar 20, 2023
@RossBencina RossBencina added the src-common Common sources in /src/common label Mar 20, 2023
@RossBencina
Copy link
Collaborator

Looking good. I think we should add a new error code. Perhaps call it paCanNotInitializeRecursively but maybe someone has a better idea for the name. That would be added here:

} PaErrorCode;

With a new error text case added here:

src/common/pa_front.c Outdated Show resolved Hide resolved
@RossBencina RossBencina changed the title Pa_Initialze(): Guard against recursive calls. Pa_Initialize(): Guard against recursive calls. Mar 20, 2023
{
// a concurrent initialization is already running
PA_DEBUG(("Attempting to re-enter Pa_Initialize(), aborting!\n"));
result = paInternalError;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add new error code as described here: #794 (comment)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

src/common/pa_front.c Outdated Show resolved Hide resolved
Copy link
Collaborator

@RossBencina RossBencina left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I approve. I fixed a typo.

@RossBencina RossBencina added the final merge review Maintainers flag as ready to make a final merge decision label Mar 31, 2023
@RossBencina
Copy link
Collaborator

@dechamps @MichalPetryka I think this is ready to merge. Please could you confirm that it fixes #766 or advise if you have any objections. If you're happy use the GitHub review feature to approve it.

@dechamps
Copy link
Contributor

dechamps commented Apr 2, 2023

The code looks like by me. I'll let @MichalPetryka confirm that it fixes #766 as they're the reporter.

If you're happy use the GitHub review feature to approve it.

I don't think I have the project permissions to do that. (It's either that or I can't find the button.)

@@ -154,6 +154,7 @@ static PaUtilHostApiRepresentation **hostApis_ = 0;
static int hostApisCount_ = 0;
static int defaultHostApiIndex_ = 0;
static int initializationCount_ = 0;
static int initializing_ = 0;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be marked volatile to prevent the compiler from doing threading unsafe optimizations here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My original version had this volatile due to the assumption that this will prevent the compiler form reordering.
However this assumption is not guaranteed and fortunately also not necessary, because the compiler cannot move code across external function calls like InitializeHostApis() in our case.

Another aspect is thread safety. The volatile keyword can be part of the solution but, we need also atomic test_and_set() which is not available in C89. Since thread safety is not a requirement here and also not build in any other call the using code is responsible anyway and it is no point in this PR.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that initialization and shutdown are rare enough that using a mutex here to ensure thread safety would be okay. @RossBencina What do you say?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A mutex will create a deadlock in the recursive case.
IMHO this PR is good enough, protecting Portaudio in concurrent situation is not required for the original problem.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a good discussion of thread safety. But currently PortAudio is not thread safe. This fix prevents a crash caused by a stack overflow. It does not solve the thread safety issue but it is a step in the right direction. We can consider full thread safety in a later PR.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that initialization and shutdown are rare enough that using a mutex here to ensure thread safety would be okay.

This is a reasonable point. However, PortAudio is a single threaded API, and this patch is intended to prevent recursion on a single thread. According to our API semantics Pa_Initialize() may not be called concurrently on two threads, and even our initializationCount_ mechanism is not thread-safe. Furthermore, we currently have no portable mutex infrastructure so adding a mutex here is a non-trivial change.

So my vote would be to merge this as-is and worry about whether initialize/terminate, or indeed the whole API, should be made thread-safe as a separate issue.

@@ -154,6 +154,7 @@ static PaUtilHostApiRepresentation **hostApis_ = 0;
static int hostApisCount_ = 0;
static int defaultHostApiIndex_ = 0;
static int initializationCount_ = 0;
static int initializing_ = 0;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a good discussion of thread safety. But currently PortAudio is not thread safe. This fix prevents a crash caused by a stack overflow. It does not solve the thread safety issue but it is a step in the right direction. We can consider full thread safety in a later PR.

@RossBencina
Copy link
Collaborator

@MichalPetryka outside your multi-threaded thread-safety concerns could you please confirm that this patch fixes the originally identified issue #766.

@RossBencina
Copy link
Collaborator

I don't think I have the project permissions to do that. (It's either that or I can't find the button.)

@dechamps Go to the "Files Changed" tab and at the top right there is a green "Review Changes" button.

@RossBencina
Copy link
Collaborator

I've created #808 for discussing multi-thread issues.

@MichalPetryka
Copy link
Contributor

@MichalPetryka outside your multi-threaded thread-safety concerns could you please confirm that this patch fixes the originally identified issue #766.

Yeah, it does.

@RossBencina RossBencina merged commit c8b9dd2 into PortAudio:master Apr 4, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
final merge review Maintainers flag as ready to make a final merge decision src-common Common sources in /src/common
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Crash: recursive Pa_Initialize(), FlexAsio
5 participants