Skip to content

Retry copying a file while its source is briefly in use - #20635

Draft
yasumorishima wants to merge 1 commit into
nvaccess:masterfrom
yasumorishima:i20118-retry-copy
Draft

Retry copying a file while its source is briefly in use#20635
yasumorishima wants to merge 1 commit into
nvaccess:masterfrom
yasumorishima:i20118-retry-copy

Conversation

@yasumorishima

Copy link
Copy Markdown

Link to issue number:

Fixes #20118

Summary of the issue:

Copying the current user configuration to the system configuration, so that it is used on the sign-in and other secure screens, fails with "cannot copy NVDA user settings" while some files are copied and others are not.

config._setSystemConfig walks the user configuration and calls installer.tryCopyFile for every file. tryCopyFile raises as soon as CopyFile fails and no destination file was created, so a single source file that another process still holds open aborts the whole copy.

In the report, a database in the user configuration was still open while NVDA was leaving the UAC screen, which matches @seanbudd's reading of the cause in the issue.

Description of user facing changes:

Copying the configuration to the system configuration no longer fails because a file was briefly in use.

Description of developer facing changes:

installer.tryCopyFile takes two new optional arguments, numRetries (default 6) and retryInterval (default 0.5). Existing callers are unaffected.

Description of development approach:

tryRemoveFile in the same module already retries six times at half second intervals, so tryCopyFile now follows that pattern rather than introducing a new one.

The retry applies only when the copy failed and no destination file exists, which is the case where the source could not be read. When the destination does exist the copy failed while overwriting it, and that path is unchanged: the existing file is still scheduled for deletion and the copy is attempted once more.

Testing strategy:

Unit tests in tests/unit/test_installer.py cover four cases: success without retrying, retry until success, the configured retryInterval being used for each wait, and failure once the retries are exhausted. CopyFile and time.sleep are patched, so the tests assert the retry behaviour rather than filesystem timing.

CI on my fork is green, including the installer system tests, which exercise tryCopyFile through copyProgramFiles during a real installation.

I have not reproduced the original failure, since it depends on another process holding a configuration file open at the moment the copy runs. The change is therefore verified as retry behaviour rather than as a fix confirmed against the reported reproduction.

Known issues with pull request:

@CyrilleB79 noted in the issue that it would be useful to tell the user which files could not be copied. That changes what the user is told rather than whether the copy succeeds, so it is not part of this change.

Code Review Checklist:

  • Documentation:
    • Change log entry
    • User Documentation
    • Developer / Technical Documentation
    • Context sensitive help for GUI changes
  • Testing:
    • Unit tests
    • System (end to end) tests
    • Manual testing
  • UX of all users considered:
    • Speech
    • Braille
    • Low Vision
    • Different web browsers
    • Localization in other languages / culture than English
  • API is compatible with existing add-ons.
  • Security precautions taken.

tryCopyFile raised as soon as CopyFile failed and no destination file
had been created, which aborts the whole operation it belongs to.
Copying the user configuration to the system configuration walks every
file, so a single source file which another process still holds open,
such as a database left open while leaving the UAC screen, fails the
entire copy and the user is told their settings could not be copied.

Retry that case before giving up, mirroring tryRemoveFile, which already
retries six times at half second intervals. Failing to overwrite an
existing destination file is unchanged and still goes straight to
replacing it.
@seanbudd

Copy link
Copy Markdown
Member

I understand that the original issue is hard to reproduce consistently, but have you tested the "happy path" i.e. have you tested copying the files successfully using your new code?

@seanbudd

Copy link
Copy Markdown
Member

Have you tried reproducing by opening a file with notepad or similar?

@seanbudd
seanbudd marked this pull request as draft August 13, 2026 00:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

error copying NVDA user settings

2 participants