-
Notifications
You must be signed in to change notification settings - Fork 6.6k
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
Fix for settings crash on toggling enable button for any PowerToy #6620
Fix for settings crash on toggling enable button for any PowerToy #6620
Conversation
…pen the file everytime
…eneral view model value directly instead of opening and reading the value from a file each time
@alekhya. Is it possible to abstract the data for the GeneralSettingsViewModel that is shared across view models into an Implementation of an Interface that can be dependency injected instead of statically referenced. I think this would improve the code in the following ways.
|
@alekhyareddy28 What will happen if for some reason writing |
Can you please eloborate why the writing to settings.json file would fail by the runner (I verified that runner writes it as expected)? If it does, then I think it is a bug on the runner end and should be fixed rather than having the settings process try to re-open and read the settings.json file each time. @ryanbodrug-microsoft can correct me here. If we do want to avoid the situation stated by @somil55 then I can't see any other approach than to have retry statements in all the places where we try to open settings. |
@alekhyareddy28 One situation would be if Also, would it be possible to move the writing logic from runner to settings ? |
We wouldn't be able to move it to the settings because that wouldn't be backward compatible. Further discussion about this was done in issue #5955. |
@somil55 IMHO potential failure on write is another reason to centralize access to the settings. Each view model shouldn't need to synchronize and ensure resiliency wrt to serialization/deserialization of the the data individually. I think that issue could be treated separately though. |
@ryanbodrug-microsoft I agree that centralizing settings would tackle these issue and it can be handled separately. Thanks for your clarification. |
… time the general settings page is loaded the information is being read because isInitialized property could not be ignored during serialization
@ryanbodrug-microsoft, I've made the changes as suggested. Now we have a wrapper singleton class, namely I've not touched settingsutils.cs and the file handing/ipc. I was thinking if we need to make any changes to unify that, we can do so after we get your refactoring/testing PR in. Validated the following:
|
src/core/Microsoft.PowerToys.Settings.UI.Lib/Interface/IGeneralSettingsData.cs
Outdated
Show resolved
Hide resolved
@ryanbodrug-microsoft, I've made the suggested changes. There is now a generic singleton class Right now, FZ, shortcut guide and power preview use this interface along with GeneralSettings. I've validated the a change in the settings UI in each of these reflects in the actual powertoy (other than preview handlers which seem to be on all the time). As suggested, I've added a lock during initialization of I shall look into migrating the other PT settings to this repository once I get a better understanding of the way in which each of them accesses the disk/passes the information to runner. I hvn't moved the IPC delegates to settingsUtils from the view models yet. Shall do that separately as this PR is getting quite big. Thanks for patiently reviewing this PR 😄 |
Also, to add, the GetFile function should ideally not be needed in the long run. Previously GetSettings was just reading from a file and did not have a check to see if the file existed or not. Since GetSettings has been modified to create the file if it does not exist, GetFile does what getSettings previously used to. This is because in two cases, the default.json file of KBM and settings.json of PT Run, these two files are assumed to be created by runner (if they don't exist) and not settings. Hence, the |
src/core/Microsoft.PowerToys.Settings.UI.Lib/SettingsRepository`1.cs
Outdated
Show resolved
Hide resolved
OutGoingGeneralSettings snd = new OutGoingGeneralSettings(generalSettings); | ||
|
||
// Set the status of FancyZones in the general settings configuration | ||
GeneralSettingsConfig.Enabled.FancyZones = value; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was hoping that we were going to encapsulate this in the settings repository/settingsutils. Without this, how does someone know when it's appropriate to use IPC as in this case vs SaveSettings. Also to truly fix this issue we may need to synchronize write / reads across the IPC boundary. We would have to do this in a bunch of different places.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ryanbodrug-microsoft, these are the changes that I've made since you last reviewed-
- unify the way the Modulename is accessed. It was redeclared in multiple places and this would cause an issue if the name is changed only in one place. All the module names are accessed using the Settings.ModuleName, eg: ShortcutGuideSettings.ModuleName.
- Modified the settingsConfig in settingsRepository so that the we don't have to use TypeOf and categorize the objects into GeneralSettings and BasePTModuleSettings.
- GetFile is now a private function. Modified the logic of KBM default.json access and PT Run so that we can re-use GetSettings instead of GetFile.
- Added UpgradeSettingsConfiguration to the ISettingsConfig interface so that the settings file can be upgraded based on some condition. Presently, only the GeneralSettings file is utilizing this to change the PT Version number based on the old PT version and the current PT version that it receives from the helper function. Verified that if the PT version is lower in the general settings.json file, settings saves the file with the new version info.
- The naming for the PowerToys was inconsistent and the variables were redeclared in multiple places. To have the settings.ModuleName as the main name, all other places should refer to that name. In the tests file the module name for ImgResizer was "ImageResizer" and not "Image Resizer".
As discussed offline, there is still some refactoring that needs to be done for settings, however it would be nice to get this in for this release as it fixes the crash and I'll make the following changes as a part of another PR -
- Move IPC from the shell page to settingsUtils.
- Have the viewmodels utilize the settings utils to communicate with runner rather than through having a delegate passed to each of them.
- We should be able to make the code such that settings doesn't have to save the file directly, it can rather communicate this information to the runner and the runner can save the information.
- As stated previously, only FZ, Shortcutguide, and powerPreview use settings repository. It should be expanded to the rest so that ideally
SaveSettings
is made private. - If we can somehow have runner tell the settings that it has received the information and has successfully stored it, then we can notify the user if something goes wrong there instead of having settings and runner running completely independently. I need to look more into the way IPC works to do this..
…le places and this would cause an issue if the name is changed only in one place. All the module names are accessed using the <T>Settings.ModuleName, eg: ShortcutGuideSettings.ModuleName.
…json access and PT Run so that we can re-use GetSettings instead of GetFile.
…o that the settings file can be upgraded based on some condition. Presently, only the GeneralSettings file is utilizing this to change the PT Version number based on the old PT version and the current PT version that it receives from the helper function. Verified that if the PT version is lower in the general settings.json file, settings saves the file with the new version info.
…redeclared in multiple places. To have the settings.ModuleName as the main name, all other places should refer to that name. In the tests file the module name for ImgResizer was 'ImageResizer' and not 'Image Resizer'.
…se because the code does not use types to create a new BasePTModule object
Summary of the Pull Request
What is this about?
This PR fixes the file IO Exception that the file is in use by another process.
This behavior is noticed when toggling the enable button on any of the pages.
PR Checklist
Info on Pull Request
What does this include?
The general settings.json file on being accessed by settings was throwing a file in use IOException because it was being used by another process.
The way settings and runner worked before this PR is as follows: the settings on start-up checks if the general settings.json file exists and reads from it, if not it creates a new one. The runner on the other hand during start-up does not save to the file (
apply_general_settings
is passed with a false save argument). There is no contention during this part.However, the issue occurs when settings tries to open the general settings.json file everytime it needs information in any viewmodel or converter. When any change is made in the settings, that information is communicated to the runner and it is the runner's responsibility to write to the settings.json file. However, since we have one process continuously trying to read from a file and the other writing to the same file, there is contention.
To fix this issue, the following changes have been made -
GeneralSettingsConfig
a public static variable.GeneralSettingsConfig
in the settings process and passed to the runner which is now the only process accessing that file.Might possibly be related to #6527 as well (even this is a IOException in the settings hotkeycontrol).
Validation Steps Performed
How does someone test & validate?