Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Fix some race conditions in concurrent initialization #3611

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

Closed
wants to merge 2 commits into from

Conversation

alexcrichton
Copy link
Contributor

Some of the travis tests I have for the git2-rs Rust library for libgit2 have been failing a lot recently with the error:

src/global.c:38: git__on_shutdown: Assertion `count <= 8 && count > 0' failed.

Curious as to why this was happening, I scrutinized some of the calls to git__on_shutdown, and I think the latter of these two commits may be the cause of this. Unfortunately I wasn't ever able to reproduce locally, so I'm not sure that this fixes the bug I'm seeing, but it seems like these may want to be fixed regardless!

When concurrently calling filter_registry_initialize, it's possible for two
threads to try to initialize the global `git__filter_registry` variable. One
thread will fail the CAS, returning the current value of `git__filter_registry`,
but it will then unfortunately *free* that current value.

Instead store the found global registry in another local variable and free just
our own local copy.
If this function was concurrently called, it was possible for all threads
entering to call `git__on_shutdown` which could possibly trigger the assert that
there aren't too many shutdown handlers (as each thread entering would try to
register one).

This adds an atomic variable to count the number of threads entering, and only
the first will register a shutdown handler. Additionally, the shutdown handler
no longer flags itself as not having been set, as it is indeed still set.
@ethomson
Copy link
Member

What do you mean exactly by "concurrent initialization"... Are you running git_libgit2_init from multiple threads?

@alexcrichton
Copy link
Contributor Author

Ah sorry, by concurrent initialization I meant on behalf of the threads calling these functions, for example if two threads call filter_registry_initialize or git_sysdir_get I think these situations will arise.

@carlosmn
Copy link
Member

The filter initialisation looks correct, though @ethomson has done a larger refactor around them in #3597.

It does look like we would need better synchronization around git_sysdir_get() but this doesn't look like it's enough. This would still call the guess function multiple times. I think what this needs is a mutex which we enter once we notice that we haven't set the sysdir yet. Upon entering the mutex we would check again and set if we are the first ones. This would be safe and still allow the normal path to be fast. We do something similar in the packfille code.

@alexcrichton
Copy link
Contributor Author

Ok, sounds like some more invasive changes are probably needed here, so closing.

@alexcrichton alexcrichton deleted the fix-some-races branch February 19, 2016 22:18
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

Successfully merging this pull request may close these issues.

3 participants