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
This commit is contained in:
Jon Cinque
2021-09-22 23:10:35 +02:00
committed by GitHub
parent 0eb0d7f73b
commit 567f30aa1a
10 changed files with 107 additions and 40 deletions

View File

@@ -15,7 +15,7 @@ use {
},
std::{
net::SocketAddr,
path::Path,
path::{Path, PathBuf},
sync::{Arc, RwLock},
thread::{self, Builder},
time::{Duration, SystemTime},
@@ -171,7 +171,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")
@@ -212,9 +212,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<gen_client::Client, RpcError> {
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",

View File

@@ -24,8 +24,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 +168,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 +304,8 @@ fn main() {
});
}
let mut ledger_fd_lock = fd_lock::RwLock::new(fs::File::open(&ledger_path).unwrap());
let _ledger_lock = ledger_fd_lock.try_write().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 +389,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![];

View File

@@ -3,9 +3,17 @@ pub use solana_core::test_validator;
pub use solana_gossip::cluster_info::MINIMUM_VALIDATOR_PORT_RANGE_WIDTH;
use {
console::style,
fd_lock::{RwLock, RwLockWriteGuard},
indicatif::{ProgressDrawTarget, ProgressStyle},
log::*,
std::{borrow::Cow, env, fmt::Display, process::exit, thread::JoinHandle},
std::{
borrow::Cow,
env,
fmt::Display,
fs::{File, OpenOptions},
path::Path,
process::exit,
thread::JoinHandle,
},
};
pub mod admin_rpc_service;
@@ -13,7 +21,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 +44,23 @@ pub fn redirect_stderr_to_file(logfile: Option<String>) -> Option<JoinHandle<()>
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 +74,12 @@ pub fn redirect_stderr_to_file(logfile: Option<String>) -> Option<JoinHandle<()>
}
#[cfg(not(unix))]
{
println!("logging to a file is not supported on this platform");
println!("logrotate is not supported on this platform");
solana_logger::setup_file_with_default(&logfile, filter);
None
}
}
};
solana_logger::setup_with_default("solana=info");
logger_thread
}
}
pub fn port_validator(port: String) -> Result<(), String> {
@@ -133,3 +145,27 @@ impl ProgressBar {
}
}
}
pub fn ledger_lockfile(ledger_path: &Path) -> RwLock<File> {
let lockfile = ledger_path.join("ledger.lock");
fd_lock::RwLock::new(
OpenOptions::new()
.write(true)
.create(true)
.open(&lockfile)
.unwrap(),
)
}
pub fn lock_ledger<'path, 'lock>(
ledger_path: &'path Path,
ledger_lockfile: &'lock mut RwLock<File>,
) -> RwLockWriteGuard<'lock, File> {
ledger_lockfile.try_write().unwrap_or_else(|_| {
println!(
"Error: Unable to lock {} directory. Check if another validator is running",
ledger_path.display()
);
exit(1);
})
}

View File

@@ -66,8 +66,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},
@@ -2848,14 +2848,8 @@ pub fn main() {
})
});
let mut ledger_fd_lock = fd_lock::RwLock::new(fs::File::open(&ledger_path).unwrap());
let _ledger_lock = ledger_fd_lock.try_write().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()));
let admin_service_cluster_info = Arc::new(RwLock::new(None));