8000 config_file: fix race when creating an iterator by pks-t · Pull Request #5282 · libgit2/libgit2 · GitHub
[go: up one dir, main page]

Skip to content

config_file: fix race when creating an iterator #5282

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

Merged
merged 5 commits into from
Nov 5, 2019

Conversation

pks-t
Copy link
Member
@pks-t pks-t commented Oct 24, 2019

When creating a configuration file iterator, then we first refresh the
backend and then afterwards duplicate all refreshed configuration
entries into the iterator in order to avoid seeing any concurrent
modifications of the entries while iterating. The duplication of entries
is not guarded, though, as we do not increase the refcount of the
entries that we duplicate right now. This opens us up for a race, as
another thread may concurrently refresh the repository configuration and
thus swap out the current set of entries. As we didn't increase the
refcount, this may lead to the entries being free'd while we iterate
over them in the first thread.

Fix the issue by properly handling the lifecycle of the backend's
entries via config_file_entries_take and git_config_entries_free,
respectively.


I think this may be the likely cause of #5281, as it fixes a severe race condition in exactly the code path that #5281 shows.

@eaigner
Copy link
eaigner commented Oct 26, 2019

Does clar provide a facility to test async behavior?

@pks-t
Copy link
Member Author
pks-t commented Oct 26, 2019 via email

@eaigner
Copy link
eaigner commented Oct 26, 2019

Yes, I know. Still, its hard to avoid race conditions if you are not using libgit in a commandline fashion, at which point one might just as well parse git output ;)

Copy link
@eaigner eaigner left a comment

Choose a reason for hiding this comment

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

looks good to me

@pks-t pks-t mentioned this pull request Nov 5, 2019
2 tasks
Copy link
Contributor
@tiennou tiennou left a comment

Choose a reason for hiding this comment

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

LGTM, thanks for the fixes and cleanups @pks-t 🙇 !

pks-t added 5 commits November 5, 2019 12:34
The configuration snapshot backend has been extracted from the old files
backend back in 2bff84b (config_file: separate out read-only backend,
2019-07-26). To keep code churn manageable, the local functions weren't
renamed yet and thus still have references to the old diskfile backend.
Rename them accordingly to make them easier to understand.
As with the predecessing commit, this commit renames backend functions
of the configuration file backend. This helps to clearly separate
functionality and also to be able to see from backtraces which backend
is currently in use.
The function to take a reference to the config file's config entries
currently returns the reference via return value. Due to this, it's
harder than necessary to integrate into our typical coding style, as one
needs to make sure that a proper error code is set before erroring out
from the caller. This bites us in `config_file_delete`, where we call
`goto out` directly when `config_file_entries_take` returns `NULL`, but
we actually forget to set up the error code and thus return success.

Fix the issue by refactoring the function to return an error code and
pass the reference via an out-pointer.
When creating a configuration file iterator, then we first refresh the
backend and then afterwards duplicate all refreshed configuration
entries into the iterator in order to avoid seeing any concurrent
modifications of the entries while iterating. The duplication of entries
is not guarded, though, as we do not increase the refcount of the
entries that we duplicate right now. This opens us up for a race, as
another thread may concurrently refresh the repository configuration and
thus swap out the current set of entries. As we didn't increase the
refcount, this may lead to the entries being free'd while we iterate
over them in the first thread.

Fix the issue by properly handling the lifecycle of the backend's
entries via `config_file_entries_take` and `git_config_entries_free`,
respectively.
@pks-t pks-t force-pushed the pks/config-file-iterator-race branch from 63bc45e to 56b203a Compare November 5, 2019 11:35
@pks-t
Copy link
Member Author
pks-t commented Nov 5, 2019

Rebased to fix conflicts with #5293

@pks-t pks-t merged commit 5d773a1 into libgit2:master Nov 5, 2019
@pks-t
Copy link
Member Author
pks-t commented Nov 5, 2019

Thanks @eaigner and @tiennou for your reviews!

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
0