From 8b3539bc11639f2feaebdbb2fcbc9578806f5702 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Sun, 31 Jan 2016 12:58:08 +0000 Subject: core: prevent the database from being used by multiple daemons A boost lock is used to determine whether more than one process wants to access the database. The boost file_lock doesn't seem to like locking directories, so we use an arbitrary file in it. This allows to still run two daemons if they have different database directories (ie, LMDB/BDB, different data directories). --- src/cryptonote_core/cryptonote_core.cpp | 41 +++++++++++++++++++++++++++++++++ src/cryptonote_core/cryptonote_core.h | 5 ++++ 2 files changed, 46 insertions(+) (limited to 'src') diff --git a/src/cryptonote_core/cryptonote_core.cpp b/src/cryptonote_core/cryptonote_core.cpp index ac0be5a07..8d50e8bfd 100644 --- a/src/cryptonote_core/cryptonote_core.cpp +++ b/src/cryptonote_core/cryptonote_core.cpp @@ -218,6 +218,39 @@ namespace cryptonote return m_blockchain_storage.get_alternative_blocks_count(); } //----------------------------------------------------------------------------------------------- + bool core::lock_db_directory(const boost::filesystem::path &path) + { + // boost doesn't like locking directories... + const boost::filesystem::path lock_path = path / ".daemon_lock"; + + try + { + // ensure the file exists + std::ofstream(lock_path.string(), std::ios::out).close(); + + db_lock = boost::interprocess::file_lock(lock_path.string().c_str()); + LOG_PRINT_L1("Locking " << lock_path.string()); + if (!db_lock.try_lock()) + { + LOG_PRINT_L0("Failed to lock " << lock_path.string()); + return false; + } + return true; + } + catch (const std::exception &e) + { + LOG_PRINT_L0("Error trying to lock " << lock_path.string() << ": " << e.what()); + return false; + } + } + //----------------------------------------------------------------------------------------------- + bool core::unlock_db_directory() + { + db_lock.unlock(); + db_lock = boost::interprocess::file_lock(); + return true; + } + //----------------------------------------------------------------------------------------------- bool core::init(const boost::program_options::variables_map& vm) { bool r = handle_command_line(vm); @@ -280,6 +313,13 @@ namespace cryptonote folder /= db->get_db_name(); LOG_PRINT_L0("Loading blockchain from folder " << folder.string() << " ..."); + if (!lock_db_directory (folder)) + { + LOG_ERROR ("Failed to lock " << folder); + delete db; + return false; + } + const std::string filename = folder.string(); // temporarily default to fastest:async:1000 blockchain_db_sync_mode sync_mode = db_async; @@ -398,6 +438,7 @@ namespace cryptonote { m_blockchain_storage.deinit(); } + unlock_db_directory(); return true; } //----------------------------------------------------------------------------------------------- diff --git a/src/cryptonote_core/cryptonote_core.h b/src/cryptonote_core/cryptonote_core.h index 662f65b5a..90fdfefca 100644 --- a/src/cryptonote_core/cryptonote_core.h +++ b/src/cryptonote_core/cryptonote_core.h @@ -34,6 +34,7 @@ #include #include +#include #include "p2p/net_node_common.h" #include "cryptonote_protocol/cryptonote_protocol_handler_common.h" @@ -172,6 +173,8 @@ namespace cryptonote void graceful_exit(); bool check_fork_time(); bool relay_txpool_transactions(); + bool lock_db_directory(const boost::filesystem::path &path); + bool unlock_db_directory(); static std::atomic m_fast_exit; bool m_test_drop_download = true; @@ -205,6 +208,8 @@ namespace cryptonote time_t m_last_json_checkpoints_update; std::atomic_flag m_checkpoints_updating; + + boost::interprocess::file_lock db_lock; }; } -- cgit v1.2.3