feat: fix deadlocks

This commit is contained in:
Cyrix126 2024-10-10 19:45:41 +02:00
parent 5230d46d93
commit 387f386573
10 changed files with 538 additions and 540 deletions

View file

@ -27,6 +27,12 @@ impl eframe::App for App {
// These values are checked multiple times so
// might as well check only once here to save
// on a bunch of [.lock().unwrap()]s.
debug!("App | Locking and collecting Node state...");
let node = self.node.lock().unwrap();
let node_is_alive = node.is_alive();
let node_is_waiting = node.is_waiting();
let node_state = node.state;
drop(node);
debug!("App | Locking and collecting P2Pool state...");
let p2pool = self.p2pool.lock().unwrap();
let p2pool_is_alive = p2pool.is_alive();
@ -49,14 +55,9 @@ impl eframe::App for App {
let xvb = self.xvb.lock().unwrap();
let xvb_is_alive = xvb.is_alive();
let xvb_is_waiting = xvb.is_waiting();
let xvb_is_running = xvb.state == ProcessState::Alive;
let xvb_state = xvb.state;
drop(xvb);
debug!("App | Locking and collecting Node state...");
let node = self.node.lock().unwrap();
let node_is_alive = node.is_alive();
let node_is_waiting = node.is_waiting();
let node_state = node.state;
drop(node);
// This sets the top level Ui dimensions.
// Used as a reference for other uis.
@ -139,6 +140,7 @@ impl eframe::App for App {
xmrig_is_alive,
xmrig_proxy_is_alive,
xvb_is_alive,
xvb_is_running,
);
}
}

View file

@ -1,6 +1,5 @@
use crate::app::keys::KeyPressed;
use crate::app::Tab;
use crate::helper::ProcessState;
use crate::utils::constants::*;
use crate::utils::errors::{ErrorButtons, ErrorFerris};
use egui::*;
@ -25,6 +24,7 @@ impl crate::app::App {
xmrig_is_alive: bool,
xmrig_proxy_is_alive: bool,
xvb_is_alive: bool,
xvb_is_running: bool,
) {
// Middle panel, contents of the [Tab]
debug!("App | Rendering CENTRAL_PANEL (tab contents)");
@ -43,12 +43,14 @@ impl crate::app::App {
let distro = true;
#[cfg(not(feature = "distro"))]
let distro = false;
let node_gui_len = self.node_api.lock().unwrap().output.len();
let p2pool_gui_len = self.p2pool_api.lock().unwrap().output.len();
let xmrig_gui_len = self.xmrig_api.lock().unwrap().output.len();
let xmrig_proxy_gui_len = self.xmrig_proxy_api.lock().unwrap().output.len();
let gupax_p2pool_api = self.gupax_p2pool_api.lock().unwrap();
let debug_info = format!(
"Gupax version: {}\n
Bundled Node version: {}\n
Bundled P2Pool version: {}\n
Bundled XMRig version: {}\n
Bundled XMRig-Proxy version: {}\n
@ -114,6 +116,7 @@ path_xmr: {:#?}\n
self.state.gupax.absolute_p2pool_path.display(),
self.state.gupax.absolute_xmrig_path.display(),
self.state.gupax.absolute_xp_path.display(),
node_gui_len,
p2pool_gui_len,
xmrig_gui_len,
xmrig_proxy_gui_len,
@ -181,7 +184,7 @@ path_xmr: {:#?}\n
}
Tab::Xvb => {
debug!("App | Entering [XvB] Tab");
crate::disk::state::Xvb::show(&mut self.state.xvb, self.size, &self.state.p2pool.address, ctx, ui, &self.xvb_api, &self.xmrig_api, self.xvb.lock().unwrap().state == ProcessState::Alive);
crate::disk::state::Xvb::show(&mut self.state.xvb, self.size, &self.state.p2pool.address, ctx, ui, &self.xvb_api, &self.xmrig_api, xvb_is_running);
}
}
});

View file

@ -369,8 +369,12 @@ impl Update {
info!("Update | Saving state...");
let original_version = og.lock().unwrap().version.clone();
og.lock().unwrap().version = state_ver;
match State::save(&mut og.lock().unwrap(), &state_path) {
Ok(_) => info!("Update ... OK"),
let mut state = og.lock().unwrap().to_owned();
match State::save(&mut state, &state_path) {
Ok(_) => {
info!("Update ... OK");
*og.lock().unwrap() = state;
}
Err(e) => {
warn!("Update | Saving state ... FAIL: {}", e);
og.lock().unwrap().version = original_version;

View file

@ -466,39 +466,39 @@ impl Helper {
// 2. Lock... EVERYTHING!
let mut lock = helper.lock().unwrap();
debug!("Helper | Locking (1/15) ... [helper]");
debug!("Helper | Locked (1/17) ... [helper]");
let node = node.lock().unwrap();
debug!("Helper | Locking (2/15) ... [helper]");
debug!("Helper | Locked (2/17) ... [node]");
let p2pool = p2pool.lock().unwrap();
debug!("Helper | Locking (3/15) ... [p2pool]");
debug!("Helper | Locked (3/17) ... [p2pool]");
let xmrig = xmrig.lock().unwrap();
debug!("Helper | Locking (4/15) ... [xmrig]");
debug!("Helper | Locked (4/17) ... [xmrig]");
let xmrig_proxy = xmrig_proxy.lock().unwrap();
debug!("Helper | Locking (5/15) ... [xmrig_proxy]");
debug!("Helper | Locked (5/17) ... [xmrig_proxy]");
let xvb = xvb.lock().unwrap();
debug!("Helper | Locking (6/15) ... [xvb]");
debug!("Helper | Locked (6/17) ... [xvb]");
let mut lock_pub_sys = pub_sys.lock().unwrap();
debug!("Helper | Locking (8/15) ... [gui_api_node]");
debug!("Helper | Locked (8/17) ... [pub_sys]");
let mut gui_api_node = gui_api_node.lock().unwrap();
debug!("Helper | Locking (7/15) ... [pub_sys]");
debug!("Helper | Locked (7/17) ... [gui_api_node]");
let mut gui_api_p2pool = gui_api_p2pool.lock().unwrap();
debug!("Helper | Locking (8/15) ... [gui_api_p2pool]");
debug!("Helper | Locked (9/17) ... [gui_api_p2pool]");
let mut gui_api_xmrig = gui_api_xmrig.lock().unwrap();
debug!("Helper | Locking (9/15) ... [gui_api_xmrig]");
debug!("Helper | Locked (10/17) ... [gui_api_xmrig]");
let mut gui_api_xp = gui_api_xp.lock().unwrap();
debug!("Helper | Locking (10/15) ... [gui_api_xp]");
debug!("Helper | Locked (11/17) ... [gui_api_xp]");
let mut gui_api_xvb = gui_api_xvb.lock().unwrap();
debug!("Helper | Locking (11/15) ... [gui_api_xvb]");
debug!("Helper | Locked (12/17) ... [gui_api_xvb]");
let mut pub_api_node = pub_api_node.lock().unwrap();
debug!("Helper | Locking (14/15) ... [pub_api_node]");
debug!("Helper | Locked (13/17) ... [pub_api_node]");
let mut pub_api_p2pool = pub_api_p2pool.lock().unwrap();
debug!("Helper | Locking (14/15) ... [pub_api_p2pool]");
debug!("Helper | Locked (14/17) ... [pub_api_p2pool]");
let mut pub_api_xmrig = pub_api_xmrig.lock().unwrap();
debug!("Helper | Locking (13/15) ... [pub_api_xmrig]");
debug!("Helper | Locked (15/17) ... [pub_api_xmrig]");
let mut pub_api_xp = pub_api_xp.lock().unwrap();
debug!("Helper | Locking (14/15) ... [pub_api_xp]");
debug!("Helper | Locked (16/17) ... [pub_api_xp]");
let mut pub_api_xvb = pub_api_xvb.lock().unwrap();
debug!("Helper | Locking (15/15) ... [pub_api_xvb]");
debug!("Helper | Locked (17/17) ... [pub_api_xvb]");
// Calculate Gupax's uptime always.
lock.uptime = HumanTime::into_human(lock.instant.elapsed());
// If [Node] is alive...
@ -558,39 +558,39 @@ impl Helper {
// 3. Drop... (almost) EVERYTHING... IN REVERSE!
drop(lock_pub_sys);
debug!("Helper | Unlocking (1/12) ... [pub_sys]");
debug!("Helper | Unlocking (1/17) ... [pub_sys]");
drop(xvb);
debug!("Helper | Unlocking (2/12) ... [xvb]");
debug!("Helper | Unlocking (2/17) ... [xvb]");
drop(xmrig_proxy);
debug!("Helper | Unlocking (3/12) ... [xmrig_proxy]");
debug!("Helper | Unlocking (3/17) ... [xmrig_proxy]");
drop(xmrig);
debug!("Helper | Unlocking (3/12) ... [xmrig]");
debug!("Helper | Unlocking (4/17) ... [xmrig]");
drop(p2pool);
debug!("Helper | Unlocking (4/12) ... [p2pool]");
debug!("Helper | Unlocking (5/17) ... [p2pool]");
drop(node);
debug!("Helper | Unlocking (4/12) ... [node]");
debug!("Helper | Unlocking (6/17) ... [node]");
drop(pub_api_xvb);
debug!("Helper | Unlocking (5/12) ... [pub_api_xvb]");
debug!("Helper | Unlocking (7/17) ... [pub_api_xvb]");
drop(pub_api_xp);
debug!("Helper | Unlocking (6/12) ... [pub_api_xp]");
debug!("Helper | Unlocking (8/17) ... [pub_api_xp]");
drop(pub_api_xmrig);
debug!("Helper | Unlocking (6/12) ... [pub_api_xmrig]");
debug!("Helper | Unlocking (9/17) ... [pub_api_xmrig]");
drop(pub_api_p2pool);
debug!("Helper | Unlocking (7/12) ... [pub_api_p2pool]");
debug!("Helper | Unlocking (10/17) ... [pub_api_p2pool]");
drop(pub_api_node);
debug!("Helper | Unlocking (7/12) ... [node]");
debug!("Helper | Unlocking (11/17) ... [pub_api_node]");
drop(gui_api_xvb);
debug!("Helper | Unlocking (8/12) ... [gui_api_xvb]");
debug!("Helper | Unlocking (12/17) ... [gui_api_xvb]");
drop(gui_api_xp);
debug!("Helper | Unlocking (9/12) ... [gui_api_xp]");
debug!("Helper | Unlocking (13/17) ... [gui_api_xp]");
drop(gui_api_xmrig);
debug!("Helper | Unlocking (10/12) ... [gui_api_xmrig]");
debug!("Helper | Unlocking (14/17) ... [gui_api_xmrig]");
drop(gui_api_p2pool);
debug!("Helper | Unlocking (11/12) ... [gui_api_p2pool]");
debug!("Helper | Unlocking (15/17) ... [gui_api_p2pool]");
drop(gui_api_node);
debug!("Helper | Unlocking (11/12) ... [node]");
debug!("Helper | Unlocking (16/17) ... [gui_api_node]");
drop(lock);
debug!("Helper | Unlocking (12/12) ... [helper]");
debug!("Helper | Unlocking (17/17) ... [helper]");
// 4. Calculate if we should sleep or not.
// If we should sleep, how long?
@ -686,71 +686,63 @@ fn check_user_input(process: &Arc<Mutex<Process>>, stdin: &mut Box<dyn std::io::
}
}
fn signal_end(
process: &Arc<Mutex<Process>>,
process: &mut Process,
child_pty: &Arc<Mutex<Box<dyn Child + Sync + Send>>>,
start: &Instant,
gui_api_output_raw: &mut String,
) -> bool {
if process.lock().unwrap().signal == ProcessSignal::Stop {
debug!("{} Watchdog | Stop SIGNAL caught", process.lock().unwrap().name);
let mut child_pty_lock = child_pty.lock().unwrap();
if process.signal == ProcessSignal::Stop {
debug!("{} Watchdog | Stop SIGNAL caught", process.name);
// This actually sends a SIGHUP to p2pool (closes the PTY, hangs up on p2pool)
if let Err(e) = child_pty.lock().unwrap().kill() {
error!("{} Watchdog | Kill error: {}", process.lock().unwrap().name, e);
if let Err(e) = child_pty_lock.kill() {
error!("{} Watchdog | Kill error: {}", process.name, e);
}
// Wait to get the exit status
let exit_status = match child_pty.lock().unwrap().wait() {
let exit_status = match child_pty_lock.wait() {
Ok(e) => {
if e.success() {
process.lock().unwrap().state = ProcessState::Dead;
process.state = ProcessState::Dead;
"Successful"
} else {
process.lock().unwrap().state = ProcessState::Failed;
process.state = ProcessState::Failed;
"Failed"
}
}
_ => {
process.lock().unwrap().state = ProcessState::Failed;
process.state = ProcessState::Failed;
"Unknown Error"
}
};
let uptime = HumanTime::into_human(start.elapsed());
info!(
"{} Watchdog | Stopped ... Uptime was: [{}], Exit status: [{}]",
process.lock().unwrap().name,
uptime,
exit_status
process.name, uptime, exit_status
);
// This is written directly into the GUI API, because sometimes the 900ms event loop can't catch it.
let name = process.name.to_owned();
if let Err(e) = writeln!(
gui_api_output_raw,
"{}\n{} stopped | Uptime: [{}] | Exit status: [{}]\n{}\n\n\n\n",
process.lock().unwrap().name,
HORI_CONSOLE,
uptime,
exit_status,
HORI_CONSOLE
name, HORI_CONSOLE, uptime, exit_status, HORI_CONSOLE
) {
error!(
"{} Watchdog | GUI Uptime/Exit status write failed: {}",
process.lock().unwrap().name,
e
name, e
);
}
process.lock().unwrap().signal = ProcessSignal::None;
debug!(
"{} Watchdog | Stop SIGNAL done, breaking",
process.lock().unwrap().name,
);
process.signal = ProcessSignal::None;
debug!("{} Watchdog | Stop SIGNAL done, breaking", process.name,);
return true;
// Check RESTART
} else if process.lock().unwrap().signal == ProcessSignal::Restart {
debug!("{} Watchdog | Restart SIGNAL caught", process.lock().unwrap().name,);
} else if process.signal == ProcessSignal::Restart {
debug!("{} Watchdog | Restart SIGNAL caught", process.name,);
// This actually sends a SIGHUP to p2pool (closes the PTY, hangs up on p2pool)
if let Err(e) = child_pty.lock().unwrap().kill() {
error!("{} Watchdog | Kill error: {}", process.lock().unwrap().name, e);
if let Err(e) = child_pty_lock.kill() {
error!("{} Watchdog | Kill error: {}", process.name, e);
}
// Wait to get the exit status
let exit_status = match child_pty.lock().unwrap().wait() {
let exit_status = match child_pty_lock.wait() {
Ok(e) => {
if e.success() {
"Successful"
@ -763,31 +755,22 @@ fn signal_end(
let uptime = HumanTime::into_human(start.elapsed());
info!(
"{} Watchdog | Stopped ... Uptime was: [{}], Exit status: [{}]",
process.lock().unwrap().name,
uptime,
exit_status
process.name, uptime, exit_status
);
// This is written directly into the GUI API, because sometimes the 900ms event loop can't catch it.
let name = process.name.to_owned();
if let Err(e) = writeln!(
gui_api_output_raw,
"{}\n{} stopped | Uptime: [{}] | Exit status: [{}]\n{}\n\n\n\n",
process.lock().unwrap().name,
HORI_CONSOLE,
uptime,
exit_status,
HORI_CONSOLE
name, HORI_CONSOLE, uptime, exit_status, HORI_CONSOLE
) {
error!(
"{} Watchdog | GUI Uptime/Exit status write failed: {}",
process.lock().unwrap().name,
e
name, e
);
}
process.lock().unwrap().state = ProcessState::Waiting;
debug!(
"{} Watchdog | Restart SIGNAL done, breaking",
process.lock().unwrap().name,
);
process.state = ProcessState::Waiting;
debug!("{} Watchdog | Restart SIGNAL done, breaking", process.name,);
return true;
}
false
@ -796,8 +779,8 @@ async fn sleep_end_loop(now: Instant, name: ProcessName) {
// Sleep (only if 999ms hasn't passed)
let elapsed = now.elapsed().as_millis();
// Since logic goes off if less than 1000, casting should be safe
if elapsed < 999 {
let sleep = (999 - elapsed) as u64;
if elapsed < 1000 {
let sleep = (1000 - elapsed) as u64;
debug!(
"{} Watchdog | END OF LOOP - Sleeping for [{}]ms...",
name, sleep

View file

@ -227,7 +227,8 @@ impl Helper {
loop {
let now = Instant::now();
debug!("Node Watchdog | ----------- Start of loop -----------");
{
// scope to drop locked mutex before the sleep
// check state
if check_died(
&child_pty,
@ -239,7 +240,7 @@ impl Helper {
}
// check signal
if signal_end(
process,
&mut process.lock().unwrap(),
&child_pty,
&start,
&mut gui_api.lock().unwrap().output,
@ -253,8 +254,10 @@ impl Helper {
// Check if logs need resetting
debug!("Node Watchdog | Attempting GUI log reset check");
{
let mut lock = gui_api.lock().unwrap();
Self::check_reset_gui_output(&mut lock.output, ProcessName::Node);
Self::check_reset_gui_output(
&mut gui_api.lock().unwrap().output,
ProcessName::Node,
);
}
// No need to check output since monerod has a sufficient API
// Always update from output
@ -264,7 +267,9 @@ impl Helper {
debug!("Node Watchdog | Attempting HTTP API request...");
match PrivNodeApi::request_api(&client, &state).await {
Ok(priv_api) => {
debug!("Node Watchdog | HTTP API request OK, attempting [update_from_priv()]");
debug!(
"Node Watchdog | HTTP API request OK, attempting [update_from_priv()]"
);
if priv_api.result.synchronized && priv_api.result.status == "OK" {
process.lock().unwrap().state = ProcessState::Alive
}
@ -280,6 +285,7 @@ impl Helper {
}
}
}
}
// do not use more than 1 second for the loop
sleep_end_loop(now, ProcessName::Node).await;
}

View file

@ -527,8 +527,8 @@ impl Helper {
// Set timer
let now = Instant::now();
debug!("P2Pool Watchdog | ----------- Start of loop -----------");
{
gui_api.lock().unwrap().tick = (last_p2pool_request.elapsed().as_secs() % 60) as u8;
// Check if the process is secretly died without us knowing :)
if check_died(
&child_pty,
@ -541,7 +541,7 @@ impl Helper {
// Check SIGNAL
if signal_end(
&process,
&mut process.lock().unwrap(),
&child_pty,
&start,
&mut gui_api.lock().unwrap().output,
@ -558,12 +558,14 @@ impl Helper {
// Always update from output
debug!("P2Pool Watchdog | Starting [update_from_output()]");
let mut process_lock = process.lock().unwrap();
let mut pub_api_lock = pub_api.lock().unwrap();
PubP2poolApi::update_from_output(
&pub_api,
&mut pub_api_lock,
&output_parse,
&output_pub,
start.elapsed(),
&process,
&mut process_lock,
);
// Read [local] API
@ -572,7 +574,7 @@ impl Helper {
// Deserialize
if let Ok(local_api) = PrivP2poolLocalApi::from_str(&string) {
// Update the structs.
PubP2poolApi::update_from_local(&pub_api, local_api);
PubP2poolApi::update_from_local(&mut pub_api_lock, local_api);
}
}
// If more than 1 minute has passed, read the other API files.
@ -582,7 +584,7 @@ impl Helper {
// check if value is 100k or under and request immediately if that's the case. fixed in release of p2pool including commit https://github.com/SChernykh/p2pool/commit/64a199be6dec7924b41f857a401086f25e1ec9be
if (last_p2pool_request_expired
|| pub_api.lock().unwrap().p2pool_difficulty_u64 <= 100000)
&& process.lock().unwrap().state == ProcessState::Alive
&& process_lock.state == ProcessState::Alive
{
debug!("P2Pool Watchdog | Attempting [network] & [pool] API file read");
if let (Ok(network_api), Ok(pool_api)) = (
@ -593,7 +595,11 @@ impl Helper {
PrivP2poolNetworkApi::from_str(&network_api),
PrivP2poolPoolApi::from_str(&pool_api),
) {
PubP2poolApi::update_from_network_pool(&pub_api, network_api, pool_api);
PubP2poolApi::update_from_network_pool(
&mut pub_api_lock,
network_api,
pool_api,
);
last_p2pool_request = tokio::time::Instant::now();
}
}
@ -601,9 +607,8 @@ impl Helper {
let last_status_request_expired =
last_status_request.elapsed() >= Duration::from_secs(60);
if (last_status_request_expired || first_loop)
&& process.lock().unwrap().state == ProcessState::Alive
&& process_lock.state == ProcessState::Alive
{
debug!("P2Pool Watchdog | Reading status output of p2pool node");
#[cfg(target_os = "windows")]
@ -625,11 +630,8 @@ impl Helper {
if first_loop {
first_loop = false;
}
} // end of scope to drop lock
sleep_end_loop(now, ProcessName::P2pool).await;
debug!(
"P2Pool Watchdog | END OF LOOP - Tick: [{}/60]",
gui_api.lock().unwrap().tick,
);
}
// 5. If loop broke, we must be done here.
@ -826,46 +828,39 @@ impl PubP2poolApi {
// Mutate "watchdog"'s [PubP2poolApi] with data the process output.
pub(super) fn update_from_output(
public: &Arc<Mutex<Self>>,
public: &mut Self,
output_parse: &Arc<Mutex<String>>,
output_pub: &Arc<Mutex<String>>,
elapsed: std::time::Duration,
process: &Arc<Mutex<Process>>,
process: &mut Process,
) {
// 1. Take the process's current output buffer and combine it with Pub (if not empty)
let mut output_pub = output_pub.lock().unwrap();
if !output_pub.is_empty() {
public
.lock()
.unwrap()
.output
.push_str(&std::mem::take(&mut *output_pub));
public.output.push_str(&std::mem::take(&mut *output_pub));
}
// 2. Parse the full STDOUT
let mut output_parse = output_parse.lock().unwrap();
let (payouts_new, xmr_new) = Self::calc_payouts_and_xmr(&output_parse);
// Check for "SYNCHRONIZED" only if we aren't already.
if process.lock().unwrap().state == ProcessState::Syncing {
if process.state == ProcessState::Syncing {
// look for depth 0
if P2POOL_REGEX.depth_0.is_match(&output_parse) {
process.lock().unwrap().state = ProcessState::Alive;
process.state = ProcessState::Alive;
}
}
// check if zmq server still alive
if process.lock().unwrap().state == ProcessState::Alive
&& contains_zmq_connection_lost(&output_parse)
{
if process.state == ProcessState::Alive && contains_zmq_connection_lost(&output_parse) {
// node zmq is not responding, p2pool is not ready
process.lock().unwrap().state = ProcessState::Syncing;
process.state = ProcessState::Syncing;
}
// 3. Throw away [output_parse]
output_parse.clear();
drop(output_parse);
// 4. Add to current values
let mut public = public.lock().unwrap();
let (payouts, xmr) = (public.payouts + payouts_new, public.xmr + xmr_new);
// 5. Calculate hour/day/month given elapsed time
@ -912,13 +907,12 @@ impl PubP2poolApi {
xmr_hour,
xmr_day,
xmr_month,
..std::mem::take(&mut *public)
..std::mem::take(public)
};
}
// Mutate [PubP2poolApi] with data from a [PrivP2poolLocalApi] and the process output.
pub(super) fn update_from_local(public: &Arc<Mutex<Self>>, local: PrivP2poolLocalApi) {
let mut public = public.lock().unwrap();
pub(super) fn update_from_local(public: &mut Self, local: PrivP2poolLocalApi) {
*public = Self {
hashrate_15m: HumanNumber::from_u64(local.hashrate_15m),
hashrate_1h: HumanNumber::from_u64(local.hashrate_1h),
@ -934,11 +928,11 @@ impl PubP2poolApi {
// Mutate [PubP2poolApi] with data from a [PrivP2pool(Network|Pool)Api].
pub(super) fn update_from_network_pool(
public: &Arc<Mutex<Self>>,
public: &mut Self,
net: PrivP2poolNetworkApi,
pool: PrivP2poolPoolApi,
) {
let user_hashrate = public.lock().unwrap().user_p2pool_hashrate_u64; // The user's total P2Pool hashrate
let user_hashrate = public.user_p2pool_hashrate_u64; // The user's total P2Pool hashrate
let monero_difficulty = net.difficulty;
let monero_hashrate = monero_difficulty / MONERO_BLOCK_TIME_IN_SECONDS;
let p2pool_hashrate = pool.pool_statistics.hashRate;
@ -980,7 +974,6 @@ impl PubP2poolApi {
p2pool_difficulty / user_hashrate,
));
}
let mut public = public.lock().unwrap();
*public = Self {
p2pool_difficulty_u64: p2pool_difficulty,
monero_difficulty_u64: monero_difficulty,

View file

@ -116,8 +116,14 @@ Uptime = 0h 2m 4s
"".to_string(),
PathBuf::new(),
)));
PubP2poolApi::update_from_output(&public, &output_parse, &output_pub, elapsed, &process);
let public = public.lock().unwrap();
let mut public = public.lock().unwrap();
PubP2poolApi::update_from_output(
&mut public,
&output_parse,
&output_pub,
elapsed,
&mut process.lock().unwrap(),
);
println!("{:#?}", public);
assert_eq!(public.payouts, 3);
assert_eq!(public.payouts_hour, 180.0);
@ -161,8 +167,8 @@ Uptime = 0h 2m 4s
},
};
// Update Local
PubP2poolApi::update_from_local(&public, local);
let p = public.lock().unwrap();
let mut p = public.lock().unwrap();
PubP2poolApi::update_from_local(&mut p, local);
println!("AFTER LOCAL: {:#?}", p);
assert_eq!(p.hashrate_15m.to_string(), "10,000");
assert_eq!(p.hashrate_1h.to_string(), "20,000");
@ -175,10 +181,8 @@ Uptime = 0h 2m 4s
assert_eq!(p.current_effort.to_string(), "200.00%");
assert_eq!(p.connections.to_string(), "1,234");
assert_eq!(p.user_p2pool_hashrate_u64, 20000);
drop(p);
// Update Network + Pool
PubP2poolApi::update_from_network_pool(&public, network, pool);
let p = public.lock().unwrap();
PubP2poolApi::update_from_network_pool(&mut p, network, pool);
println!("AFTER NETWORK+POOL: {:#?}", p);
assert_eq!(p.monero_difficulty.to_string(), "300,000,000,000");
assert_eq!(p.monero_hashrate.to_string(), "2.500 GH/s");

View file

@ -1,12 +1,12 @@
use crate::constants::*;
use crate::helper::xrig::update_xmrig_config;
use crate::helper::{check_died, check_user_input, sleep_end_loop, Process};
use crate::helper::{arc_mut, check_died, check_user_input, sleep, sleep_end_loop, Process};
use crate::helper::{Helper, ProcessName, ProcessSignal, ProcessState};
use crate::helper::{PubXvbApi, XvbNode};
use crate::miscs::output_console;
use crate::regex::{contains_error, contains_usepool, detect_new_node_xmrig, XMRIG_REGEX};
use crate::utils::human::HumanNumber;
use crate::utils::sudo::SudoState;
use crate::{constants::*, macros::*};
use enclose::enclose;
use log::*;
use portable_pty::Child;
@ -514,7 +514,7 @@ impl Helper {
}
// Stop on [Stop/Restart] SIGNAL
if Self::xmrig_signal_end(
&process,
&mut process.lock().unwrap(),
&child_pty,
&start,
&mut gui_api.lock().unwrap().output,
@ -591,13 +591,13 @@ impl Helper {
info!("XMRig Watchdog | Watchdog thread exiting... Goodbye!");
}
fn xmrig_signal_end(
process: &Arc<Mutex<Process>>,
process: &mut Process,
child_pty: &Arc<Mutex<Box<dyn Child + Sync + Send>>>,
start: &Instant,
gui_api_output_raw: &mut String,
sudo: &Arc<Mutex<SudoState>>,
) -> bool {
let signal = process.lock().unwrap().signal;
let signal = process.signal;
if signal == ProcessSignal::Stop || signal == ProcessSignal::Restart {
debug!("XMRig Watchdog | Stop/Restart SIGNAL caught");
// macOS requires [sudo] again to kill [XMRig]
@ -616,7 +616,6 @@ impl Helper {
}
let exit_status = match child_pty.lock().unwrap().wait() {
Ok(e) => {
let mut process = process.lock().unwrap();
if e.success() {
if process.signal == ProcessSignal::Stop {
process.state = ProcessState::Dead;
@ -630,7 +629,6 @@ impl Helper {
}
}
_ => {
let mut process = process.lock().unwrap();
if process.signal == ProcessSignal::Stop {
process.state = ProcessState::Failed;
}
@ -652,7 +650,6 @@ impl Helper {
e
);
}
let mut process = process.lock().unwrap();
match process.signal {
ProcessSignal::Stop => process.signal = ProcessSignal::None,
ProcessSignal::Restart => process.state = ProcessState::Waiting,

View file

@ -371,7 +371,7 @@ impl Helper {
loop {
let now = Instant::now();
debug!("XMRig-Proxy Watchdog | ----------- Start of loop -----------");
// check state
{
if check_died(
&child_pty,
&mut process.lock().unwrap(),
@ -382,7 +382,7 @@ impl Helper {
}
// check signal
if signal_end(
process,
&mut process.lock().unwrap(),
&child_pty,
&start,
&mut gui_api.lock().unwrap().output,
@ -395,10 +395,10 @@ impl Helper {
// Check if logs need resetting
debug!("XMRig-Proxy Watchdog | Attempting GUI log reset check");
{
let mut lock = gui_api.lock().unwrap();
Self::check_reset_gui_output(&mut lock.output, ProcessName::XmrigProxy);
}
Self::check_reset_gui_output(
&mut gui_api.lock().unwrap().output,
ProcessName::XmrigProxy,
);
// Always update from output
// todo: check difference with xmrig
debug!("XMRig-Proxy Watchdog | Starting [update_from_output()]");
@ -411,7 +411,8 @@ impl Helper {
);
// update data from api
debug!("XMRig-Proxy Watchdog | Attempting HTTP API request...");
match PrivXmrigProxyApi::request_xp_api(&client, api_summary_xp, token_proxy).await {
match PrivXmrigProxyApi::request_xp_api(&client, api_summary_xp, token_proxy).await
{
Ok(priv_api) => {
debug!("XMRig-Proxy Watchdog | HTTP API request OK, attempting [update_from_priv()]");
PubXmrigProxyApi::update_from_priv(pub_api, priv_api);
@ -455,6 +456,7 @@ impl Helper {
debug!("XMRig-Proxy Process | mining on Xmrig-Proxy pool");
}
}
} // locked are dropped here
// do not use more than 1 second for the loop
sleep_end_loop(now, ProcessName::XmrigProxy).await;
}

View file

@ -208,6 +208,7 @@ impl Helper {
debug!("XvB Watchdog | ----------- Start of loop -----------");
// Set timer of loop
let start_loop = std::time::Instant::now();
{
// check if first loop the state of Xmrig-Proxy
if first_loop {
xp_alive = process_xp.lock().unwrap().state == ProcessState::Alive;
@ -279,7 +280,9 @@ impl Helper {
&& last_request.lock().unwrap().elapsed() >= Duration::from_secs(25);
let process_alive = process.lock().unwrap().state == ProcessState::Alive;
if ((last_request_expired || first_loop)
|| (*retry.lock().unwrap() || is_algo_finished || should_refresh_before_next_algo)
|| (*retry.lock().unwrap()
|| is_algo_finished
|| should_refresh_before_next_algo)
&& process_alive)
&& is_request_finished
{
@ -405,6 +408,7 @@ impl Helper {
first_loop = false;
}
// Sleep (only if 900ms hasn't passed)
}
sleep_end_loop(start_loop, ProcessName::Xvb).await;
}
}