Fix corrupted config error#15691
Conversation
eeaaab4 to
134c8eb
Compare
lukaszgo1
left a comment
There was a problem hiding this comment.
While what has been implemented here certainly fixes the issue at hand, I have a feeling that the underlying problem still remains. This is by no means a criticism, (we always solved circular imports using lazy importing), but my personal opinion is that whenever possible code should be restructured to avoid these. In this particular case NVDAHelper clearly requires importing way too much, (most of its uses only requires localLib) and should be split, however this is out of scope for this PR, and should be done in a dedicated one. the following would improve this particular situation without reorganizing too much code:
Currently logHandler requires nvwave to play sounds, yet it can only do so when nvwave is initialized. Rather than importing it lazily in the logHandler I'd defer the decision if the sound can be played, and the actual act of playing it to nvwave, by adding an extension point to the logHandler (something like onErrorLogged). When initializing nvwave it should register a function with this extension point, and in it check if nvwave is not in error, if it is not just play the error sound.
There are two points worth keeping in mint with this design:
extensionPointsimportslogHandler, so we are trading one circular import for another. Having said that we would have only one lazy import as opposed to around 10 innvwave, and several more inlogHandler, so I'd say this is a right move. To make this work the extension point inlogHandlerhas to be retrieved with a module level getter function whereextensionPointswould be lazily imported (I'd suggest usingfunctools.lru_cachewith a cache size set to 1 to create it first time it is needed, and then return cached instance)nvwaveshould be terminated incore, to make sure the function responsible for playing error sounds is not registered multiple times
In addition having system test for this issue would probably be helpful.
|
@lukaszgo1 thanks for the review and the design suggestion. @seanbudd I would like to hear your opinion on this design before implementing it; thus, I'll put this PR as ready for review, but I am totally open to the design change suggested by @lukaszgo1 if it goes in the sense of code simplification. I have some remaining questions regarding this design:
|
Yes - the fact that
I'm sorry - I haven't made myself clear enough here. What I proposed was not a
It is not |
|
Thanks @lukaszgo1 for all these indications.
How can it be?
So it seems that |
In the same way as most of our existing modules i.e. at the bottom of
I haven't considered this before, but I believe |
Sorry, I meant:
This makes sense. Maybe I will have to find more adapted names than |
See test results for failed build of commit b75a423672 |
I assumed, without looking at the code :-( that |
lukaszgo1
left a comment
There was a problem hiding this comment.
Please update the initial comment, to describe the new approach.
Also I take back my suggestion about system tests. I haven't realized that they rely on scratchpad being enabled, and that cannot be done when the provided config is not valid. It should be possible to convert them into an add-on, and set the necessary config from it, rather than just providing the preset config file, but that is certainly something for another day.
| nvwave.playWaveFile(os.path.join(globalVars.appDir, "waves", "error.wav")) | ||
| except: | ||
| pass | ||
| getOnErrorSoundRequested().notify() |
There was a problem hiding this comment.
I would have preferred a more global "pre_errorLogged" extension point, which could be more useful for add-on authors (including myself with NVDA Dev & Test Toolbox). But I am not able to define one cleanly without reintroducing more lazy imports.
@XLTechie, @lukaszgo1 any opinion on this?
There was a problem hiding this comment.
That is probably something for a separate issue / PR, but if there is a need to have more extension points in the logHandler then the circular import between it and extensionPoints has to be fixed. My first thought would be to expose an additional way to import logHandler.log (perhaps from globalVars).
| log.warning("Error saving configuration; probably read only file system") | ||
| log.debugWarning("", exc_info=True) | ||
| pass | ||
| except PermissionError: |
There was a problem hiding this comment.
are we certain no other exceptions are thrown here? wouldn't it be safer to continue to catch other exceptions and log at exception level
There was a problem hiding this comment.
Actually, other exceptions are thrown here and it was erroneous to catch all here to issue a so specific error message related to read only file system.
For an example of other exception thrown here, in NVDA 2023.3, press 3 times NVDA+control+R to restore default settings. You will get the following inappropriate warning message in the log:
WARNING - config.profileUpgrader.upgrade (09:35:01.738) - MainThread (15004):
Error saving configuration; probably read only file system
Thus I have narrowed the error filtering to PermissionError as it is already done in source/config/__init__.py for the same logged message.
If there are other exceptions that were previously catched by the filtering on Exception, they should be reported and fixed, not filtered out with a single warning.
…ccess#16017) Fix-up of nvaccess#15691. Summary of the issue: In nvaccess#15691, a new extension point has been created. Unfortunately I have forgotten to document it. Description of user facing changes Document this extension point in the dev guide as well as in the change log.
Link to issue number:
Fixes #15690
Summary of the issue:
Critical error when starting NVDA with a corrupted config file.
During config initialization, an error is logged. To check if it should play an error sound, NVDA imports
nvwave, which in turn importsnvdaHelper, which importsversionInfo, where "_" is not yet defined since translations are not initialized.Description of user facing changes
If the configuration file is corrupted, NVDA will not fail starting anymore, but will reinitialize the configuration to default as it did in NVDA 2023.1 and before.
Description of development approach
buildVersionmodule innvdaHelperinstead ofversionInfosince the latter contains localized information that we do not use. But it was not enough since "_" (underscore is still missing when importingeventHandlerorapiAlso, when investigating the issue and working on this PR, I have fixed the following minor issues:
log.debugWarning("", exc_info=True), and used theexc_infoin thelog.warningjust above. Indeed, during config initialization, log level is not yet known and thus theexc_infoinformation is not known during startup if needed.Additional questions and notes
Testing strategy:
Tested STR of #15690.
Known issues with pull request:
Code Review Checklist: