Skip to content

Commit

Permalink
Add separate multiprocess test for InterprocessMutex init and locks
Browse files Browse the repository at this point in the history
  • Loading branch information
kiburtse committed Oct 18, 2023
1 parent 749d2aa commit c584ef0
Show file tree
Hide file tree
Showing 4 changed files with 84 additions and 4 deletions.
3 changes: 3 additions & 0 deletions src/realm/util/interprocess_mutex.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,9 @@ class InterprocessMutex {
InterprocessMutex(const InterprocessMutex&) = delete;
InterprocessMutex& operator=(const InterprocessMutex&) = delete;

InterprocessMutex(InterprocessMutex&&) = default;
InterprocessMutex& operator=(InterprocessMutex&&) = default;

#if REALM_ROBUST_MUTEX_EMULATION || defined(_WIN32)
struct SharedPart {
};
Expand Down
65 changes: 65 additions & 0 deletions test/test_shared.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
#include <realm/util/features.h>
#include <realm/util/file.hpp>
#include <realm/util/safe_int_ops.hpp>
#include <realm/util/scope_exit.hpp>
#include <realm/util/terminate.hpp>
#include <realm/util/thread.hpp>
#include <realm/util/to_string.hpp>
Expand All @@ -55,6 +56,7 @@

#include "test.hpp"
#include "test_table_helper.hpp"
#include "util/spawned_process.hpp"

extern unsigned int unit_test_random_seed;

Expand Down Expand Up @@ -4345,4 +4347,67 @@ TEST(Shared_WriteToFail)
CHECK(*tr == *dest);
}

NONCONCURRENT_TEST_IF(Shared_LockFileConcurrentInit, testing_supports_spawn_process)
{
auto path = realm::test_util::get_test_path(test_context.get_test_name(), ".test-dir");
test_util::TestDirGuard test_dir(path, false);
test_dir.do_remove = SpawnedProcess::is_parent();
auto lock_prefix = std::string(path) + "/lock";

struct Mutex : InterprocessMutex {
SharedPart sp;

Mutex(Mutex&&) = default;
Mutex& operator=(Mutex&&) = default;

Mutex(const std::string& name, const std::string& lock_prefix_path)
{
set_shared_part(sp, lock_prefix_path, name);
}
~Mutex()
{
release_shared_part();
}
};

for (size_t i = 0; i < 10; ++i) {
std::vector<std::unique_ptr<SpawnedProcess>> spawned;

// create multiple processes initializing multiple same purpose locks
for (size_t j = 0; j < 10; ++j) {
spawned.emplace_back(
test_util::spawn_process(test_context.test_details.test_name, util::format("child [%1]", i)));

if (spawned.back()->is_child()) {
std::vector<Mutex> locks;

// mimic the same impl detail as in DB and hope it'd trigger some assertions
for (auto tag : {"write", "control", "versions"}) {
locks.emplace_back(tag, lock_prefix);
CHECK(locks.back().is_valid());
}

// if somehow initialization is scrambled or there is an issues with
// underlying files then it should hang here
for (int k = 0; k < 3; ++k) {
for (auto&& mutex : locks)
mutex.lock();
for (auto&& mutex : locks)
mutex.unlock();
}

exit(0);
}
}

if (SpawnedProcess::is_parent()) {
for (auto&& process : spawned)
process->wait_for_child_to_finish();

// start everytime with no lock files for mutexes
test_dir.clean_dir();
}
}
}

#endif // TEST_SHARED
11 changes: 8 additions & 3 deletions test/util/test_path.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -230,18 +230,23 @@ TestPathGuard& TestPathGuard::operator=(TestPathGuard&& other) noexcept
}


TestDirGuard::TestDirGuard(const std::string& path)
TestDirGuard::TestDirGuard(const std::string& path, bool init_clean)
: m_path(path)
{
if (!try_make_dir(path)) {
clean_dir(path);
if (init_clean)
clean_dir(path);
}
}

TestDirGuard::~TestDirGuard() noexcept
{
if (g_keep_files)
return;

if (!do_remove)
return;

try {
clean_dir(m_path);
remove_dir(m_path);
Expand All @@ -266,7 +271,7 @@ void do_clean_dir(const std::string& path, const std::string& guard_string)
// Try to avoid accidental removal of precious files due to bugs in
// TestDirGuard or TEST_DIR macro.
if (subpath.find(guard_string) == std::string::npos)
throw std::runtime_error("Bad test dir path");
throw std::runtime_error("Bad test dir path: " + path + ", guard: " + guard_string);
File::remove(subpath);
}
}
Expand Down
9 changes: 8 additions & 1 deletion test/util/test_path.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ class TestPathGuard {
/// directory, then removes the directory.
class TestDirGuard {
public:
TestDirGuard(const std::string& path);
TestDirGuard(const std::string& path, bool init_clean = true);
~TestDirGuard() noexcept;
operator std::string() const
{
Expand All @@ -131,6 +131,13 @@ class TestDirGuard {
return m_path.c_str();
}

bool do_remove = true;

void clean_dir()
{
clean_dir(m_path);
}

private:
std::string m_path;
void clean_dir(const std::string& path);
Expand Down

0 comments on commit c584ef0

Please sign in to comment.