fix(core): fix geth --init temp dir race condition (#2068)

* fix(core): fix geth --init temp dir race condition

 * previously, if multiple instances of geth were spawned concurrently,
   only one directory would be used to populate geth's genesis.json.
   this can lead to a race condition where the genesis.json would be
   re-written by a second instance, before the first instance reads the
   genesis.json for populating its db and genesis block with the geth
   --init command. this was possible because directory returned by
   std::env::temp_dir() is often shared
 * fixes the race condition by using tempfile::tempdir(), which creates
   a unique directory per call to tempdir()

* only use tempfile on non-wasm32
This commit is contained in:
Dan Cline 2023-01-21 21:13:40 -05:00 committed by GitHub
parent b8fa524e8e
commit e9a808e84f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 13 additions and 3 deletions

View File

@ -44,8 +44,10 @@ syn = { version = "1.0.107", optional = true }
proc-macro2 = { version = "1.0.50", optional = true } proc-macro2 = { version = "1.0.50", optional = true }
num_enum = "0.5.7" num_enum = "0.5.7"
[dev-dependencies] [target.'cfg(not(target_arch = "wasm32"))'.dependencies]
tempfile = { version = "3.3.0", default-features = false } tempfile = { version = "3.3.0", default-features = false }
[dev-dependencies]
serde_json = { version = "1.0.64", default-features = false } serde_json = { version = "1.0.64", default-features = false }
bincode = { version = "1.3.3", default-features = false } bincode = { version = "1.3.3", default-features = false }
once_cell = { version = "1.17.0" } once_cell = { version = "1.17.0" }

View File

@ -6,13 +6,13 @@ use crate::{
utils::secret_key_to_address, utils::secret_key_to_address,
}; };
use std::{ use std::{
env::temp_dir,
fs::{create_dir, File}, fs::{create_dir, File},
io::{BufRead, BufReader}, io::{BufRead, BufReader},
path::PathBuf, path::PathBuf,
process::{Child, ChildStderr, Command, Stdio}, process::{Child, ChildStderr, Command, Stdio},
time::{Duration, Instant}, time::{Duration, Instant},
}; };
use tempfile::tempdir;
/// How long we will wait for geth to indicate that it is ready. /// How long we will wait for geth to indicate that it is ready.
const GETH_STARTUP_TIMEOUT_MILLIS: u64 = 10_000; const GETH_STARTUP_TIMEOUT_MILLIS: u64 = 10_000;
@ -402,7 +402,11 @@ impl Geth {
if let Some(ref genesis) = self.genesis { if let Some(ref genesis) = self.genesis {
// create a temp dir to store the genesis file // create a temp dir to store the genesis file
let temp_genesis_path = temp_dir().join("genesis.json"); let temp_genesis_dir_path =
tempdir().expect("should be able to create temp dir for genesis init").into_path();
// create a temp dir to store the genesis file
let temp_genesis_path = temp_genesis_dir_path.join("genesis.json");
// create the genesis file // create the genesis file
let mut file = File::create(&temp_genesis_path).expect("could not create genesis file"); let mut file = File::create(&temp_genesis_path).expect("could not create genesis file");
@ -425,6 +429,10 @@ impl Geth {
.expect("failed to spawn geth init") .expect("failed to spawn geth init")
.wait() .wait()
.expect("failed to wait for geth init to exit"); .expect("failed to wait for geth init to exit");
// clean up the temp dir which is now persisted
std::fs::remove_dir_all(temp_genesis_dir_path)
.expect("could not remove genesis temp dir");
} }
if let Some(ref data_dir) = self.data_dir { if let Some(ref data_dir) = self.data_dir {