Skip to content

Commit

Permalink
Thread safety to fix reported race conditions
Browse files Browse the repository at this point in the history
  • Loading branch information
mon committed May 7, 2021
1 parent eb7d65e commit 2ae0fee
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 15 deletions.
13 changes: 11 additions & 2 deletions layeredfs/hook.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ using std::string;
#include <algorithm>
#include <iostream>
#include <fstream>
#include <mutex>

#include "3rd_party/MinHook.h"
#pragma comment(lib, "minhook.lib")
Expand All @@ -37,7 +38,7 @@ using std::string;
#undef max
#undef min

#define VER_STRING "2.0"
#define VER_STRING "2.1"

#ifdef _DEBUG
#define DBG_VER_STRING "_DEBUG"
Expand Down Expand Up @@ -75,7 +76,8 @@ typedef struct image {
} image_t;

// ifs_textures["data/graphics/ver04/logo.ifs/tex/4f754d4f424f092637a49a5527ece9bb"] will be "konami"
std::unordered_map<string, image_t> ifs_textures;
static std::unordered_map<string, image_t> ifs_textures;
static std::mutex ifs_textures_mtx;

typedef std::unordered_set<string> string_set;

Expand Down Expand Up @@ -234,7 +236,9 @@ bool add_images_to_list(string_set &extra_pngs, rapidxml::xml_node<> *texturelis
image_info.height = texture->height;

auto md5_path = ifs_path + "/tex/" + image_info.name_md5;
ifs_textures_mtx.lock();
ifs_textures[md5_path] = image_info;
ifs_textures_mtx.unlock();
}
}

Expand Down Expand Up @@ -340,7 +344,9 @@ void parse_texturelist(string const&path, string const&norm_path, optional<strin
image_info.height = (dimensions[3] - dimensions[2]) / 2;

auto md5_path = ifs_path + "/tex/" + image_info.name_md5;
ifs_textures_mtx.lock();
ifs_textures[md5_path] = image_info;
ifs_textures_mtx.unlock();

extra_pngs.erase(image_info.name);
}
Expand Down Expand Up @@ -466,13 +472,16 @@ bool cache_texture(string const&png_path, image_t &tex) {
}

void handle_texture(string const&norm_path, optional<string> &mod_path) {
ifs_textures_mtx.lock();
auto tex_search = ifs_textures.find(norm_path);
if (tex_search == ifs_textures.end()) {
ifs_textures_mtx.unlock();
return;
}

//logf("Mapped file %s is found!", norm_path.c_str());
auto tex = tex_search->second;
ifs_textures_mtx.unlock(); // is it safe to unlock this early? Time will tell...

// remove the /tex/, it's nicer to navigate
auto png_path = find_first_modfile(tex.ifs_mod_path + "/" + tex.name + ".png");
Expand Down
21 changes: 15 additions & 6 deletions layeredfs/modpath_handler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#include <algorithm>
#include <unordered_map>
#include <unordered_set>
#include <mutex>

#include "ramfs_demangler.h"

Expand Down Expand Up @@ -79,18 +80,26 @@ void cache_mods(void) {
// data, data2, data_op2 etc
// data is "flat", all others must have their own special subfolders
static vector<string> game_folders;
static std::mutex game_folders_mtx;

optional<string> normalise_path(string &path) {
// one-off init
if (game_folders.empty()) {
for (auto folder : folders_in_folder(".")) {
// data is the normal case we transparently handle
if (!strcmp(folder.c_str(), "data")) {
continue;
}
game_folders_mtx.lock();

// check again in case init was raced
if (game_folders.empty()) {
for (auto folder : folders_in_folder(".")) {
// data is the normal case we transparently handle
if (!strcmp(folder.c_str(), "data")) {
continue;
}

game_folders.push_back(folder + "/");
game_folders.push_back(folder + "/");
}
}
game_folders_mtx.unlock();
// all access past here is read-only, don't use the mutex any more
}

ramfs_demangler_demangle_if_possible(path);
Expand Down
21 changes: 16 additions & 5 deletions layeredfs/ramfs_demangler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@

#include <algorithm>
#include <unordered_map>
#include <mutex>
#include <optional>

#include "3rd_party/hat-trie/htrie_map.h"
Expand All @@ -48,18 +49,22 @@ typedef struct {
optional<string> mounted_path;
} file_cleanup_info_t;

unordered_map<string, file_cleanup_info_t> cleanup_map;
unordered_map<AVS_FILE, string> open_file_map;
unordered_map<void*, string> ram_load_map;
static unordered_map<string, file_cleanup_info_t> cleanup_map;
static unordered_map<AVS_FILE, string> open_file_map;
static unordered_map<void*, string> ram_load_map;
// using tries for fast prefix matches on our mangled names
tsl::htrie_map<char, string> ramfs_map;
tsl::htrie_map<char, string> mangling_map;
static tsl::htrie_map<char, string> ramfs_map;
static tsl::htrie_map<char, string> mangling_map;

static std::mutex mangling_mtx;

void ramfs_demangler_on_fs_open(const std::string& norm_path, AVS_FILE open_result) {
if (open_result < 0 || !string_ends_with(norm_path.c_str(), ".ifs")) {
return;
}

const std::lock_guard<std::mutex> lock(mangling_mtx);

auto existing_info = cleanup_map.find(norm_path);
if (existing_info != cleanup_map.end()) {
file_cleanup_info_t cleanup = existing_info->second;
Expand Down Expand Up @@ -87,6 +92,8 @@ void ramfs_demangler_on_fs_open(const std::string& norm_path, AVS_FILE open_resu
}

void ramfs_demangler_on_fs_read(AVS_FILE context, void* dest) {
const std::lock_guard<std::mutex> lock(mangling_mtx);

auto find = open_file_map.find(context);
if (find != open_file_map.end()) {
auto path = find->second;
Expand All @@ -102,6 +109,8 @@ void ramfs_demangler_on_fs_read(AVS_FILE context, void* dest) {
}

void ramfs_demangler_on_fs_mount(const char* mountpoint, const char* fsroot, const char* fstype, const char* flags) {
const std::lock_guard<std::mutex> lock(mangling_mtx);

if (!strcmp(fstype, "ramfs")) {
void* buffer;

Expand Down Expand Up @@ -150,6 +159,8 @@ void ramfs_demangler_on_fs_mount(const char* mountpoint, const char* fsroot, con
}

void ramfs_demangler_demangle_if_possible(std::string& raw_path) {
const std::lock_guard<std::mutex> lock(mangling_mtx);

auto search = mangling_map.longest_prefix(raw_path);
if (search != mangling_map.end()) {
//logf_verbose("can demangle %s to %s", search.key().c_str(), search->c_str());
Expand Down
13 changes: 11 additions & 2 deletions layeredfs/utils.cpp
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
#include "utils.h"
#include "avs.h"

#include <mutex>

#define SUPPRESS_PRINTF

void logf(char* fmt, ...) {
static std::mutex log_mutex;
static FILE* logfile = NULL;
static bool tried_to_open = false;
va_list args;
Expand All @@ -14,11 +17,17 @@ void logf(char* fmt, ...) {
printf("\n");
#endif
// don't reopen every time: slow as shit
if (!logfile && !tried_to_open) {
fopen_s(&logfile, "ifs_hook.log", "w");
if (!tried_to_open) {
const std::lock_guard<std::mutex> lock(log_mutex);

if (!logfile) {
fopen_s(&logfile, "ifs_hook.log", "w");
}
tried_to_open = true;
}
if (logfile) {
const std::lock_guard<std::mutex> lock(log_mutex);

va_start(args, fmt);
vfprintf(logfile, fmt, args);
va_end(args);
Expand Down

0 comments on commit 2ae0fee

Please sign in to comment.