mirror of
https://github.com/mimblewimble/grin.git
synced 2025-02-01 17:01:09 +03:00
use fs2 advisory file lock on startup (#2600)
This commit is contained in:
parent
5dc01b3de6
commit
48b7421d1e
4 changed files with 57 additions and 1 deletions
11
Cargo.lock
generated
11
Cargo.lock
generated
|
@ -669,6 +669,15 @@ name = "foreign-types-shared"
|
||||||
version = "0.1.1"
|
version = "0.1.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "fs2"
|
||||||
|
version = "0.4.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "fuchsia-cprng"
|
name = "fuchsia-cprng"
|
||||||
version = "0.1.1"
|
version = "0.1.1"
|
||||||
|
@ -947,6 +956,7 @@ dependencies = [
|
||||||
"blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)",
|
"blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"bufstream 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
"bufstream 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
"chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"fs2 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
|
"futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"grin_api 1.0.1",
|
"grin_api 1.0.1",
|
||||||
"grin_chain 1.0.1",
|
"grin_chain 1.0.1",
|
||||||
|
@ -3215,6 +3225,7 @@ dependencies = [
|
||||||
"checksum fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3"
|
"checksum fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3"
|
||||||
"checksum foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1"
|
"checksum foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1"
|
||||||
"checksum foreign-types-shared 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"
|
"checksum foreign-types-shared 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"
|
||||||
|
"checksum fs2 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "9564fc758e15025b46aa6643b1b77d047d1a56a1aea6e01002ac0c7026876213"
|
||||||
"checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba"
|
"checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba"
|
||||||
"checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82"
|
"checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82"
|
||||||
"checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7"
|
"checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7"
|
||||||
|
|
|
@ -11,6 +11,7 @@ edition = "2018"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
hyper = "0.12"
|
hyper = "0.12"
|
||||||
|
fs2 = "0.4"
|
||||||
futures = "0.1"
|
futures = "0.1"
|
||||||
http = "0.1"
|
http = "0.1"
|
||||||
hyper-staticfile = "0.3"
|
hyper-staticfile = "0.3"
|
||||||
|
|
|
@ -48,6 +48,8 @@ pub enum Error {
|
||||||
Pool(pool::PoolError),
|
Pool(pool::PoolError),
|
||||||
/// Invalid Arguments.
|
/// Invalid Arguments.
|
||||||
ArgumentError(String),
|
ArgumentError(String),
|
||||||
|
/// Error originating from some I/O operation (likely a file on disk).
|
||||||
|
IOError(std::io::Error),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<core::block::Error> for Error {
|
impl From<core::block::Error> for Error {
|
||||||
|
@ -60,7 +62,11 @@ impl From<chain::Error> for Error {
|
||||||
Error::Chain(e)
|
Error::Chain(e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
impl From<std::io::Error> for Error {
|
||||||
|
fn from(e: std::io::Error) -> Error {
|
||||||
|
Error::IOError(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
impl From<p2p::Error> for Error {
|
impl From<p2p::Error> for Error {
|
||||||
fn from(e: p2p::Error) -> Error {
|
fn from(e: p2p::Error) -> Error {
|
||||||
Error::P2P(e)
|
Error::P2P(e)
|
||||||
|
|
|
@ -16,9 +16,15 @@
|
||||||
//! the peer-to-peer server, the blockchain and the transaction pool) and acts
|
//! the peer-to-peer server, the blockchain and the transaction pool) and acts
|
||||||
//! as a facade.
|
//! as a facade.
|
||||||
|
|
||||||
|
use std::fs;
|
||||||
|
use std::fs::File;
|
||||||
|
use std::io::prelude::*;
|
||||||
|
use std::path::Path;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::{thread, time};
|
use std::{thread, time};
|
||||||
|
|
||||||
|
use fs2::FileExt;
|
||||||
|
|
||||||
use crate::api;
|
use crate::api;
|
||||||
use crate::api::TLSConfig;
|
use crate::api::TLSConfig;
|
||||||
use crate::chain;
|
use crate::chain;
|
||||||
|
@ -59,6 +65,8 @@ pub struct Server {
|
||||||
state_info: ServerStateInfo,
|
state_info: ServerStateInfo,
|
||||||
/// Stop flag
|
/// Stop flag
|
||||||
pub stop_state: Arc<Mutex<StopState>>,
|
pub stop_state: Arc<Mutex<StopState>>,
|
||||||
|
/// Maintain a lock_file so we do not run multiple Grin nodes from same dir.
|
||||||
|
lock_file: Arc<File>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Server {
|
impl Server {
|
||||||
|
@ -102,8 +110,36 @@ impl Server {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Exclusive (advisory) lock_file to ensure we do not run multiple
|
||||||
|
// instance of grin server from the same dir.
|
||||||
|
// This uses fs2 and should be safe cross-platform unless somebody abuses the file itself.
|
||||||
|
fn one_grin_at_a_time(config: &ServerConfig) -> Result<Arc<File>, Error> {
|
||||||
|
let path = Path::new(&config.db_root);
|
||||||
|
fs::create_dir_all(path.clone())?;
|
||||||
|
let path = path.join("grin.lock");
|
||||||
|
let lock_file = fs::OpenOptions::new()
|
||||||
|
.read(true)
|
||||||
|
.write(true)
|
||||||
|
.create(true)
|
||||||
|
.open(&path)?;
|
||||||
|
lock_file.try_lock_exclusive().map_err(|e| {
|
||||||
|
let mut stderr = std::io::stderr();
|
||||||
|
writeln!(
|
||||||
|
&mut stderr,
|
||||||
|
"Failed to lock {:?} (grin server already running?)",
|
||||||
|
path
|
||||||
|
)
|
||||||
|
.expect("Could not write to stderr");
|
||||||
|
e
|
||||||
|
})?;
|
||||||
|
Ok(Arc::new(lock_file))
|
||||||
|
}
|
||||||
|
|
||||||
/// Instantiates a new server associated with the provided future reactor.
|
/// Instantiates a new server associated with the provided future reactor.
|
||||||
pub fn new(config: ServerConfig) -> Result<Server, Error> {
|
pub fn new(config: ServerConfig) -> Result<Server, Error> {
|
||||||
|
// Obtain our lock_file or fail immediately with an error.
|
||||||
|
let lock_file = Server::one_grin_at_a_time(&config)?;
|
||||||
|
|
||||||
// Defaults to None (optional) in config file.
|
// Defaults to None (optional) in config file.
|
||||||
// This translates to false here.
|
// This translates to false here.
|
||||||
let archive_mode = match config.archive_mode {
|
let archive_mode = match config.archive_mode {
|
||||||
|
@ -264,6 +300,7 @@ impl Server {
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
stop_state,
|
stop_state,
|
||||||
|
lock_file,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -451,6 +488,7 @@ impl Server {
|
||||||
pub fn stop(&self) {
|
pub fn stop(&self) {
|
||||||
self.p2p.stop();
|
self.p2p.stop();
|
||||||
self.stop_state.lock().stop();
|
self.stop_state.lock().stop();
|
||||||
|
let _ = self.lock_file.unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Pause the p2p server.
|
/// Pause the p2p server.
|
||||||
|
|
Loading…
Reference in a new issue