C++/Go/Python
Game Developer

Немного про стремные хаки, которые работают

В игровом движке dava.engine, в классе файла под андроидом есть код, который 10 раз подряд пытается открыть файл и засыпает на 100 милисекунд, если открыть не получилось.

...
if (isFileExistOnRealFS)
{
    int32 openFileAttempt = 1;
    while (!file && (openFileAttempt++ <= 10))
    {
        if (attributes & File::WRITE)
        {
            file = FileAPI::OpenFile(path, "r+b");
        }
        else
        {
            file = FileAPI::OpenFile(path, "rb");
        }
    
        if (!file)
        {
            Logger::Error("can't open existing file: %s attempt: %d, errno: %s",
                          path.c_str(), openFileAttempt, strerror(errno));
            Thread::Sleep(100);
        }
    } // end while
}

Казалось бы, зачем? Этот код появился после фикса бага в DLC (downloadable content) - только что скаченный файл при попытки открытия был недоступен. Эмпирически вывели, что после 8 попыток файл гарантированно открывался. Вот и вставили 10 (на всякий случай!) попыток на открытие.

Стоит отметить, что есть похожий хак в коде chromium - попытка удаления файла два раза подряд.

if (!file_util::Delete(db_name, false) &&
    !file_util::Delete(db_name, false)) {
  // Try to delete twice. If we can't, fail.
  LOG(ERROR) << "unable to delete old TopSites file";
  return false;
}

К сожалению, наш мир не идеален и нужно понимать, что на файлы - это внешняя среда по отношению к программе, и с этой средой может твориться все что угодно - файлы могут быть использованы другими процессами (вирусы, антивирусы, системы контроля версий и прочие сканеры), баги по работе с файлами в других приложениях или же нас даже может подвести оборудование.

Если с кодом в chromium это выглядит как простое решение достаточно сложной проблемы, то в коде dava.engine это скорее хак. Проблема, очевидно, есть и с ней стоило бы разобраться. Почему временная задержка помогает? Может сообщение о завершении скачки файла пришло раньше, чем оно на самом деле произошло? Файловые дескрипторы закончились? Сторонние процессы лочат доступ?

К сожалению, узнать это будет уже сложно. Код ведь работает, а если работает - не трожь.