This repository has been archived by the owner on Apr 21, 2023. It is now read-only.
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.
Resolves #205
This pull request resolves the following issue which is encountered when changing profiles:
After some investigation, the cause of this issue looks to be due to the execution of the
get_current_profile
function on another thread, during the execution of theset_profile
function (and the removal of the mods folder).This race condition has been resolved with a mutex lock.
You can find my full writeup further below.
To reproduce
Version detail
BCML
3.9.27
Python
3.8.10
Troubleshooting
See more
The problematic workflow:
set_profile
function startsshutil.rmdir
.profile
file is removedget_current_profile
function is executed on another threadProfileModal.refreshProfiles
as part ofProfileModal.componentDidUpdate
within/src/js/Profile.jsx
get_current_profile
does not find a.profile
file, and so it creates a new (default) oneshutil.rmdir
(still as part ofset_profile
) attempts to finish by removing the mods folder (which should be empty).profile
file exists)In addition, I did not encounter this issue when there were only minor changes to implement as part of the profile switch. However, when the profile switch needed to do more work - such as toggling the Hyrule Rebalance mod - that's when these issues were observed.
Solution A - Ignorance
Adding the
ignore_errors
anddirs_exist_ok
arguments to thermtree
andcopytree
calls (within theset_profile
function), respectively, will resolve the issue in this case.With this fix, the contents of the
.profile
file, during a profile switch, can be observed as follows:This solution seemingly resolves the issue however the underlying problem (a race condition) still exists, and I believe under the right circumstances, a
Default
profile file would be created after a legitimate profile switch, leaving the mods folder in an invalid state.Solution B - Mutex lock (this PR)
A more robust solution is to eliminate the race condition on the mods folder. In this case1, specifically between
get_current_profile
andset_profile
.This is done with a simple mutex lock via
threading.Lock
- as seen in this PR - which prevents the profile check (and possible creation of a default project file) from occurring while a profile switch is in progress, and vice versa.With this fix, the contents of the
.profile
file, during a profile switch, can be observed as follows:As can be seen, no unnecessary intermediate
Default
profile is being created when compared to Solution A.Footnotes
Ideally, other destructive operations on the mods folder would be updated to utilise this new Mutex lock. ↩