From b112e4a8aaa3f0441d219653662309e0d8f339e6 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Fri, 24 Sep 2021 12:59:12 +0000 Subject: [PATCH] windows: Make solana-test-validator work (backport #20099) (#20123) * windows: Make solana-test-validator work (#20099) * windows: Make solana-test-validator work The important changes to get this going on Windows: * ledger lock needs to be done on a file instead of the directory * IPC service needs to use the Windows pipe naming scheme * always disable the JIT * file logging not possible yet because we can't redirect stderr, but this will change once env_logger fixes the pipe output target! * Integrate review feedback (cherry picked from commit 567f30aa1a5803047bad568c7d45f6b58baa16f1) # Conflicts: # validator/src/bin/solana-test-validator.rs # validator/src/lib.rs # validator/src/main.rs * Fix merge conflicts Co-authored-by: Jon Cinque --- core/benches/banking_stage.rs | 2 +- install/src/command.rs | 6 +-- scripts/cargo-install-all.sh | 1 + sys-tuner/src/main.rs | 1 + validator/src/admin_rpc_service.rs | 26 +++++++++-- validator/src/bin/solana-test-validator.rs | 22 ++++----- validator/src/lib.rs | 54 ++++++++++++++++++---- validator/src/main.rs | 15 ++---- 8 files changed, 86 insertions(+), 41 deletions(-) diff --git a/core/benches/banking_stage.rs b/core/benches/banking_stage.rs index 0d411e554d..59370c38d8 100644 --- a/core/benches/banking_stage.rs +++ b/core/benches/banking_stage.rs @@ -108,7 +108,7 @@ fn make_accounts_txs(txes: usize, mint_keypair: &Keypair, hash: Hash) -> Vec = (0..64).map(|_| thread_rng().gen()).collect(); + let sig: Vec<_> = (0..64).map(|_| thread_rng().gen::()).collect(); new.message.account_keys[0] = pubkey::new_rand(); new.message.account_keys[1] = pubkey::new_rand(); new.signatures = vec![Signature::new(&sig[0..64])]; diff --git a/install/src/command.rs b/install/src/command.rs index b8e9284351..0dc8755467 100644 --- a/install/src/command.rs +++ b/install/src/command.rs @@ -362,7 +362,7 @@ fn get_windows_path_var() -> Result, String> { Ok(Some(s)) } else { println!("the registry key HKEY_CURRENT_USER\\Environment\\PATH does not contain valid Unicode. Not modifying the PATH variable"); - return Ok(None); + Ok(None) } } Err(ref e) if e.kind() == io::ErrorKind::NotFound => Ok(Some(String::new())), @@ -391,7 +391,7 @@ fn add_to_path(new_path: &str) -> bool { if !old_path.contains(&new_path) { let mut new_path = new_path.to_string(); if !old_path.is_empty() { - new_path.push_str(";"); + new_path.push(';'); new_path.push_str(&old_path); } @@ -416,7 +416,7 @@ fn add_to_path(new_path: &str) -> bool { SendMessageTimeoutA( HWND_BROADCAST, WM_SETTINGCHANGE, - 0 as WPARAM, + 0_usize, "Environment\0".as_ptr() as LPARAM, SMTO_ABORTIFHUNG, 5000, diff --git a/scripts/cargo-install-all.sh b/scripts/cargo-install-all.sh index ae795cda98..d6458e8385 100755 --- a/scripts/cargo-install-all.sh +++ b/scripts/cargo-install-all.sh @@ -77,6 +77,7 @@ if [[ $CI_OS_NAME = windows ]]; then solana-install-init solana-keygen solana-stake-accounts + solana-test-validator solana-tokens ) else diff --git a/sys-tuner/src/main.rs b/sys-tuner/src/main.rs index e00a64b43e..36b85539a3 100644 --- a/sys-tuner/src/main.rs +++ b/sys-tuner/src/main.rs @@ -1,3 +1,4 @@ +#[cfg(not(target_family = "windows"))] use clap::{crate_description, crate_name, value_t_or_exit, App, Arg}; use log::*; diff --git a/validator/src/admin_rpc_service.rs b/validator/src/admin_rpc_service.rs index 4e23391f4a..26abe088d2 100644 --- a/validator/src/admin_rpc_service.rs +++ b/validator/src/admin_rpc_service.rs @@ -12,7 +12,7 @@ use { }, std::{ net::SocketAddr, - path::Path, + path::{Path, PathBuf}, sync::{Arc, RwLock}, thread::{self, Builder}, time::{Duration, SystemTime}, @@ -132,7 +132,7 @@ impl AdminRpc for AdminRpcImpl { // Start the Admin RPC interface pub fn run(ledger_path: &Path, metadata: AdminRpcRequestMetadata) { - let admin_rpc_path = ledger_path.join("admin.rpc"); + let admin_rpc_path = admin_rpc_path(ledger_path); let event_loop = tokio::runtime::Builder::new_multi_thread() .thread_name("sol-adminrpc-el") @@ -173,9 +173,29 @@ pub fn run(ledger_path: &Path, metadata: AdminRpcRequestMetadata) { .unwrap(); } +fn admin_rpc_path(ledger_path: &Path) -> PathBuf { + #[cfg(target_family = "windows")] + { + // More information about the wackiness of pipe names over at + // https://docs.microsoft.com/en-us/windows/win32/ipc/pipe-names + if let Some(ledger_filename) = ledger_path.file_name() { + PathBuf::from(format!( + "\\\\.\\pipe\\{}-admin.rpc", + ledger_filename.to_string_lossy() + )) + } else { + PathBuf::from("\\\\.\\pipe\\admin.rpc") + } + } + #[cfg(not(target_family = "windows"))] + { + ledger_path.join("admin.rpc") + } +} + // Connect to the Admin RPC interface pub async fn connect(ledger_path: &Path) -> std::result::Result { - let admin_rpc_path = ledger_path.join("admin.rpc"); + let admin_rpc_path = admin_rpc_path(ledger_path); if !admin_rpc_path.exists() { Err(RpcError::Client(format!( "{} does not exist", diff --git a/validator/src/bin/solana-test-validator.rs b/validator/src/bin/solana-test-validator.rs index 8e09357226..6d1a82586d 100644 --- a/validator/src/bin/solana-test-validator.rs +++ b/validator/src/bin/solana-test-validator.rs @@ -1,6 +1,5 @@ use { clap::{value_t, value_t_or_exit, App, Arg}, - fd_lock::FdLock, solana_clap_utils::{ input_parsers::{pubkey_of, pubkeys_of, value_of}, input_validators::{ @@ -24,8 +23,8 @@ use { }, solana_streamer::socket::SocketAddrSpace, solana_validator::{ - admin_rpc_service, dashboard::Dashboard, println_name_value, redirect_stderr_to_file, - test_validator::*, + admin_rpc_service, dashboard::Dashboard, ledger_lockfile, lock_ledger, println_name_value, + redirect_stderr_to_file, test_validator::*, }, std::{ collections::HashSet, @@ -168,7 +167,7 @@ fn main() { Arg::with_name("no_bpf_jit") .long("no-bpf-jit") .takes_value(false) - .help("Disable the just-in-time compiler and instead use the interpreter for BPF"), + .help("Disable the just-in-time compiler and instead use the interpreter for BPF. Windows always disables JIT."), ) .arg( Arg::with_name("slots_per_epoch") @@ -304,15 +303,8 @@ fn main() { }); } - let mut ledger_fd_lock = FdLock::new(fs::File::open(&ledger_path).unwrap()); - let _ledger_lock = ledger_fd_lock.try_lock().unwrap_or_else(|_| { - println!( - "Error: Unable to lock {} directory. Check if another validator is running", - ledger_path.display() - ); - exit(1); - }); - + let mut ledger_lock = ledger_lockfile(&ledger_path); + let _ledger_write_guard = lock_ledger(&ledger_path, &mut ledger_lock); if reset_ledger { remove_directory_contents(&ledger_path).unwrap_or_else(|err| { println!("Error: Unable to remove {}: {}", ledger_path.display(), err); @@ -396,6 +388,10 @@ fn main() { IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)), faucet_port, )); + // JIT not supported on the BPF VM in Windows currently: https://github.com/solana-labs/rbpf/issues/217 + #[cfg(target_family = "windows")] + let bpf_jit = false; + #[cfg(not(target_family = "windows"))] let bpf_jit = !matches.is_present("no_bpf_jit"); let mut programs = vec![]; diff --git a/validator/src/lib.rs b/validator/src/lib.rs index 25be76f12f..7823566d65 100644 --- a/validator/src/lib.rs +++ b/validator/src/lib.rs @@ -3,9 +3,15 @@ pub use solana_core::test_validator; pub use solana_gossip::cluster_info::MINIMUM_VALIDATOR_PORT_RANGE_WIDTH; use { console::style, + fd_lock::{FdLock, FdLockGuard}, indicatif::{ProgressDrawTarget, ProgressStyle}, - log::*, - std::{env, process::exit, thread::JoinHandle}, + std::{ + env, + fs::{File, OpenOptions}, + path::Path, + process::exit, + thread::JoinHandle, + }, }; pub mod admin_rpc_service; @@ -13,7 +19,7 @@ pub mod dashboard; #[cfg(unix)] fn redirect_stderr(filename: &str) { - use std::{fs::OpenOptions, os::unix::io::AsRawFd}; + use std::os::unix::io::AsRawFd; match OpenOptions::new() .write(true) .create(true) @@ -36,17 +42,23 @@ pub fn redirect_stderr_to_file(logfile: Option) -> Option env::set_var("RUST_BACKTRACE", "1") } - let logger_thread = match logfile { - None => None, + let filter = "solana=info"; + match logfile { + None => { + solana_logger::setup_with_default(filter); + None + } Some(logfile) => { #[cfg(unix)] { + use log::info; let signals = signal_hook::iterator::Signals::new(&[signal_hook::SIGUSR1]) .unwrap_or_else(|err| { eprintln!("Unable to register SIGUSR1 handler: {:?}", err); exit(1); }); + solana_logger::setup_with_default(filter); redirect_stderr(&logfile); Some(std::thread::spawn(move || { for signal in signals.forever() { @@ -60,14 +72,12 @@ pub fn redirect_stderr_to_file(logfile: Option) -> Option } #[cfg(not(unix))] { - println!("logging to a file is not supported on this platform"); + println!("logging to file is not supported on this platform"); + solana_logger::setup_with_default(filter); None } } - }; - - solana_logger::setup_with_default("solana=info"); - logger_thread + } } pub fn port_validator(port: String) -> Result<(), String> { @@ -133,3 +143,27 @@ impl ProgressBar { } } } + +pub fn ledger_lockfile(ledger_path: &Path) -> FdLock { + let lockfile = ledger_path.join("ledger.lock"); + FdLock::new( + OpenOptions::new() + .write(true) + .create(true) + .open(&lockfile) + .unwrap(), + ) +} + +pub fn lock_ledger<'path, 'lock>( + ledger_path: &'path Path, + ledger_lockfile: &'lock mut FdLock, +) -> FdLockGuard<'lock, File> { + ledger_lockfile.try_lock().unwrap_or_else(|_| { + println!( + "Error: Unable to lock {} directory. Check if another validator is running", + ledger_path.display() + ); + exit(1); + }) +} diff --git a/validator/src/main.rs b/validator/src/main.rs index e5ebad855d..2fae79a1e1 100644 --- a/validator/src/main.rs +++ b/validator/src/main.rs @@ -5,7 +5,6 @@ use { AppSettings, Arg, ArgMatches, SubCommand, }, console::style, - fd_lock::FdLock, log::*, rand::{seq::SliceRandom, thread_rng, Rng}, solana_clap_utils::{ @@ -59,8 +58,8 @@ use { }, solana_streamer::socket::SocketAddrSpace, solana_validator::{ - admin_rpc_service, dashboard::Dashboard, new_spinner_progress_bar, println_name_value, - redirect_stderr_to_file, + admin_rpc_service, dashboard::Dashboard, ledger_lockfile, lock_ledger, + new_spinner_progress_bar, println_name_value, redirect_stderr_to_file, }, std::{ collections::{HashSet, VecDeque}, @@ -2517,14 +2516,8 @@ pub fn main() { }) }); - let mut ledger_fd_lock = FdLock::new(fs::File::open(&ledger_path).unwrap()); - let _ledger_lock = ledger_fd_lock.try_lock().unwrap_or_else(|_| { - println!( - "Error: Unable to lock {} directory. Check if another validator is running", - ledger_path.display() - ); - exit(1); - }); + let mut ledger_lock = ledger_lockfile(&ledger_path); + let _ledger_write_guard = lock_ledger(&ledger_path, &mut ledger_lock); let start_progress = Arc::new(RwLock::new(ValidatorStartProgress::default())); admin_rpc_service::run(