1
0
mirror of https://github.com/OpenRCT2/OpenRCT2 synced 2026-01-15 11:03:00 +01:00

Fix FileWatcher (#18216)

This commit is contained in:
Silent
2022-10-24 02:35:00 +02:00
committed by GitHub
parent 58e2da72c6
commit 79660f2fe9
3 changed files with 28 additions and 26 deletions

View File

@@ -20,6 +20,7 @@
# include <unistd.h>
#endif
#include "../core/Path.hpp"
#include "../core/String.hpp"
#include "FileSystem.hpp"
#include "FileWatcher.h"
@@ -81,20 +82,20 @@ FileWatcher::WatchDescriptor::~WatchDescriptor()
}
#endif
FileWatcher::FileWatcher(const std::string& directoryPath)
FileWatcher::FileWatcher(u8string_view directoryPath)
{
#ifdef _WIN32
_path = directoryPath;
_directoryHandle = CreateFileA(
directoryPath.c_str(), FILE_LIST_DIRECTORY, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS,
nullptr);
_path = fs::u8path(directoryPath);
_directoryHandle = CreateFileW(
String::ToWideChar(directoryPath).c_str(), FILE_LIST_DIRECTORY, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, nullptr);
if (_directoryHandle == INVALID_HANDLE_VALUE)
{
throw std::runtime_error("Unable to open directory '" + directoryPath + "'");
throw std::runtime_error("Unable to open directory '" + u8string(directoryPath) + "'");
}
#elif defined(__linux__)
_fileDesc.Initialise();
_watchDescs.emplace_back(_fileDesc.Fd, directoryPath);
_watchDescs.emplace_back(_fileDesc.Fd, u8string(directoryPath));
for (auto& p : fs::recursive_directory_iterator(directoryPath))
{
if (p.status().type() == fs::file_type::directory)
@@ -105,21 +106,22 @@ FileWatcher::FileWatcher(const std::string& directoryPath)
#else
throw std::runtime_error("FileWatcher not supported on this platform.");
#endif
_watchThread = std::thread(std::bind(&FileWatcher::WatchDirectory, this));
_watchThread = std::thread(&FileWatcher::WatchDirectory, this);
}
FileWatcher::~FileWatcher()
{
#ifdef _WIN32
CancelIoEx(_directoryHandle, nullptr);
_watchThread.join();
CloseHandle(_directoryHandle);
#elif defined(__linux__)
_finished = true;
_watchThread.join();
_fileDesc.Close();
#else
return;
#endif
_watchThread.join();
}
void FileWatcher::WatchDirectory()
@@ -131,8 +133,7 @@ void FileWatcher::WatchDirectory()
_directoryHandle, eventData.data(), static_cast<DWORD>(eventData.size()), TRUE, FILE_NOTIFY_CHANGE_LAST_WRITE,
&bytesReturned, nullptr, nullptr))
{
auto onFileChanged = OnFileChanged;
if (onFileChanged)
if (bytesReturned != 0 && OnFileChanged)
{
FILE_NOTIFY_INFORMATION* notifyInfo;
size_t offset = 0;
@@ -141,10 +142,9 @@ void FileWatcher::WatchDirectory()
notifyInfo = reinterpret_cast<FILE_NOTIFY_INFORMATION*>(eventData.data() + offset);
offset += notifyInfo->NextEntryOffset;
std::wstring fileNameW(notifyInfo->FileName, notifyInfo->FileNameLength / sizeof(wchar_t));
auto fileName = String::ToUtf8(fileNameW);
auto path = fs::path(_path) / fs::path(fileName);
onFileChanged(path.u8string());
std::wstring_view fileNameW(notifyInfo->FileName, notifyInfo->FileNameLength / sizeof(wchar_t));
auto path = _path / fs::path(fileNameW);
OnFileChanged(path.u8string());
} while (notifyInfo->NextEntryOffset != 0);
}
}
@@ -175,9 +175,7 @@ void FileWatcher::WatchDirectory()
[wd](const WatchDescriptor& watchDesc) { return wd == watchDesc.Wd; });
if (findResult != _watchDescs.end())
{
auto directory = findResult->Path;
auto path = fs::path(directory) / fs::path(e->name);
onFileChanged(path);
onFileChanged(Path::Combine(findResult->Path, e->name));
}
}
offset += sizeof(inotify_event) + e->len;

View File

@@ -9,12 +9,16 @@
#pragma once
#include "String.hpp"
#include <functional>
#include <string>
#include <thread>
#include <vector>
#ifdef _WIN32
# include "FileSystem.hpp"
typedef void* HANDLE;
#endif
@@ -26,7 +30,7 @@ class FileWatcher
private:
std::thread _watchThread;
#if defined(_WIN32)
std::string _path;
fs::path _path;
HANDLE _directoryHandle{};
#elif defined(__linux__)
struct FileDescriptor
@@ -53,9 +57,9 @@ private:
#endif
public:
std::function<void(const std::string& path)> OnFileChanged;
std::function<void(u8string_view path)> OnFileChanged;
FileWatcher(const std::string& directoryPath);
FileWatcher(u8string_view directoryPath);
~FileWatcher();
private:

View File

@@ -771,8 +771,8 @@ void ScriptEngine::SetupHotReloading()
if (Path::DirectoryExists(base))
{
_pluginFileWatcher = std::make_unique<FileWatcher>(base);
_pluginFileWatcher->OnFileChanged = [this](const std::string& path) {
std::lock_guard<std::mutex> guard(_changedPluginFilesMutex);
_pluginFileWatcher->OnFileChanged = [this](u8string_view path) {
std::lock_guard guard(_changedPluginFilesMutex);
_changedPluginFiles.emplace(path);
};
_hotReloadingInitialised = true;
@@ -799,10 +799,10 @@ void ScriptEngine::DoAutoReloadPluginCheck()
void ScriptEngine::AutoReloadPlugins()
{
if (_changedPluginFiles.size() > 0)
if (!_changedPluginFiles.empty())
{
std::lock_guard<std::mutex> guard(_changedPluginFilesMutex);
for (auto& path : _changedPluginFiles)
std::lock_guard guard(_changedPluginFilesMutex);
for (const auto& path : _changedPluginFiles)
{
auto findResult = std::find_if(_plugins.begin(), _plugins.end(), [&path](const std::shared_ptr<Plugin>& plugin) {
return Path::Equals(path, plugin->GetPath());