MDEV-35983 Avoid install failures by using retry logic for file operations

Added retry logic to certain file operations during installation as a
workaround for issues caused by buggy antivirus software on Windows.

Retry logic added for WritePrivateProfileString (mysql_install_db.cc)
and renaming file in Innodb.
This commit is contained in:
Vladislav Vaintroub 2025-04-09 17:00:42 +02:00
parent 1f5d2b2010
commit 6edfdae44d
2 changed files with 34 additions and 3 deletions

View File

@ -344,10 +344,29 @@ static char *init_bootstrap_command_line(char *cmdline, size_t size)
static char my_ini_path[MAX_PATH];
/**
Wrapper for WritePrivateProfileStringA, with retries and sleeps
if file is locked by another process.
*/
static BOOL write_private_profile_string_with_retries(const char *appname,
const char *key, const char *val, const char *filename)
{
static constexpr int RETRIES=50;
static constexpr int SLEEP_MS=10;
for (int n= RETRIES;; n--)
{
if (WritePrivateProfileStringA(appname, key, val, filename))
return TRUE;
if (GetLastError() != ERROR_ACCESS_DENIED || !n)
return FALSE;
Sleep(SLEEP_MS);
}
}
static void write_myini_str(const char *key, const char* val, const char *section="mysqld")
{
DBUG_ASSERT(my_ini_path[0]);
if (!WritePrivateProfileString(section, key, val, my_ini_path))
if (!write_private_profile_string_with_retries(section, key, val, my_ini_path))
{
die("Can't write to ini file key=%s, val=%s, section=%s, Windows error %u",key,val,section,
GetLastError());

View File

@ -2314,8 +2314,20 @@ os_file_rename_func(
ut_ad(exists);
#endif /* UNIV_DEBUG */
if (MoveFileEx(oldpath, newpath, MOVEFILE_REPLACE_EXISTING)) {
return(true);
for (int retry= 50;; retry--){
if (MoveFileEx(oldpath, newpath, MOVEFILE_REPLACE_EXISTING))
return true;
if (!retry)
break;
if (GetLastError() != ERROR_SHARING_VIOLATION)
break;
// oldpath was opened by someone else (antivirus?)
//without FILE_SHARE_DELETE flag. Retry operation
Sleep(10);
}
os_file_handle_rename_error(oldpath, newpath);