diff --git a/Cargo.lock b/Cargo.lock
index 34d69b6..d81ceda 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -4,7 +4,7 @@ version = 3
 
 [[package]]
 name = "Gupax"
-version = "0.5.0"
+version = "0.7.0"
 dependencies = [
  "anyhow",
  "arti-client",
@@ -2500,9 +2500,9 @@ dependencies = [
 
 [[package]]
 name = "num-format"
-version = "0.4.3"
+version = "0.4.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "54b862ff8df690cf089058c98b183676a7ed0f974cc08b426800093227cbff3b"
+checksum = "a652d9771a63711fd3c3deb670acfbe5c30a4072e664d7a3bf5a9e1056ac72c3"
 dependencies = [
  "arrayvec 0.7.2",
  "itoa",
diff --git a/Cargo.toml b/Cargo.toml
index 0a61b52..458eece 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "Gupax"
-version = "0.5.0"
+version = "0.7.0"
 authors = ["hinto-janaiyo <hinto.janaiyo@protonmail.com>"]
 description = "GUI for P2Pool+XMRig"
 documentation = "https://github.com/hinto-janaiyo/gupax"
diff --git a/src/constants.rs b/src/constants.rs
index 01cf749..43d81c5 100644
--- a/src/constants.rs
+++ b/src/constants.rs
@@ -54,6 +54,7 @@ pub const BLACK: egui::Color32 = egui::Color32::BLACK;
 
 // [Duration] constants
 pub const SECOND: std::time::Duration = std::time::Duration::from_secs(1);
+pub const MILLI_900: std::time::Duration = std::time::Duration::from_millis(900);
 pub const TOKIO_SECOND: tokio::time::Duration = std::time::Duration::from_secs(1);
 
 // OS specific
diff --git a/src/helper.rs b/src/helper.rs
index 1300923..c2dc8f9 100644
--- a/src/helper.rs
+++ b/src/helper.rs
@@ -75,7 +75,7 @@ pub struct Process {
 	pub signal: ProcessSignal, // Did the user click [Start/Stop/Restart]?
 	start: Instant,            // Start time of process
 	pub uptime: HumanTime,     // Human readable process uptime
-	pub output: String,        // This is the process's stdout + stderr
+	pub output: String,        // This is the process's PUBLIC stdout + stderr
 	// STDIN Problem:
 	//     - User can input many many commands in 1 second
 	//     - The process loop only processes every 1 second
@@ -86,7 +86,10 @@ pub struct Process {
 	//     - When the user inputs something, push it to a [Vec]
 	//     - In the process loop, loop over every [Vec] element and
 	//       send each one individually to the process stdin
-	stdin: Option<std::process::ChildStdin>, // A handle to the process's STDIN
+	pub child: Option<Arc<Mutex<tokio::process::Child>>>,  // A handle to the actual child process
+	stdout: Option<tokio::process::ChildStdout>, // A handle to the process's STDOUT
+	stderr: Option<tokio::process::ChildStderr>, // A handle to the process's STDERR
+	stdin: Option<tokio::process::ChildStdin>, // A handle to the process's STDIN
 	pub input: Vec<String>,
 }
 
@@ -100,7 +103,10 @@ impl Process {
 			signal: ProcessSignal::None,
 			start: now,
 			uptime: HumanTime::into_human(now.elapsed()),
+			stdout: Option::None,
+			stderr: Option::None,
 			stdin: Option::None,
+			child: Option::None,
 			// P2Pool log level 1 produces a bit less than 100,000 lines a day.
 			// Assuming each line averages 80 UTF-8 scalars (80 bytes), then this
 			// initial buffer should last around a week (56MB) before resetting.
@@ -540,13 +546,17 @@ impl Helper {
 	// The tokio runtime that blocks while async reading both STDOUT/STDERR
 	// Cheaper than spawning 2 OS threads just to read 2 pipes (...right? :D)
 	#[tokio::main]
-	async fn read_stdout_stderr(process: &Arc<Mutex<Process>>, stdout: tokio::process::ChildStdout, stderr: tokio::process::ChildStderr) {
-		let process_stdout = Arc::clone(process);
-		let process_stderr = Arc::clone(process);
+	async fn read_stdout_stderr(process: Arc<Mutex<Process>>) {
+		let process_stdout = Arc::clone(&process);
+		let process_stderr = Arc::clone(&process);
+		let stdout = process.lock().unwrap().stdout.take().unwrap();
+		let stderr = process.lock().unwrap().stderr.take().unwrap();
+
 		// Create STDOUT pipe job
 		let stdout_job = tokio::spawn(async move {
 			let mut stdout_reader = BufReader::new(stdout).lines();
 			while let Ok(Some(line)) = stdout_reader.next_line().await {
+//				println!("{}", line); // For debugging.
 				writeln!(process_stdout.lock().unwrap().output, "{}", line);
 			}
 		});
@@ -554,6 +564,7 @@ impl Helper {
 		let stderr_job = tokio::spawn(async move {
 			let mut stderr_reader = BufReader::new(stderr).lines();
 			while let Ok(Some(line)) = stderr_reader.next_line().await {
+//				println!("{}", line); // For debugging.
 				writeln!(process_stderr.lock().unwrap().output, "{}", line);
 			}
 		});
@@ -573,15 +584,15 @@ impl Helper {
 		// [Simple]
 		if state.simple {
 			// Build the p2pool argument
-			let (ip, rpc, zmq) = crate::node::enum_to_ip_rpc_zmq_tuple(state.node); // Get: (IP, RPC, ZMQ)
-			args.push(format!("--wallet {}", state.address));        // Wallet Address
-			args.push(format!("--host {}", ip));                     // IP Address
-			args.push(format!("--rpc-port {}", rpc));                // RPC Port
-			args.push(format!("--zmq-port {}", zmq));                // ZMQ Port
-			args.push(format!("--data-api {}", api_path.display())); // API Path
-			args.push("--local-api".to_string());                    // Enable API
-			args.push("--no-color".to_string());                     // Remove color escape sequences, Gupax terminal can't parse it :(
-			args.push("--mini".to_string());                         // P2Pool Mini
+			let (ip, rpc, zmq) = crate::node::enum_to_ip_rpc_zmq_tuple(state.node);         // Get: (IP, RPC, ZMQ)
+			args.push("--wallet".to_string()); args.push(state.address.clone());            // Wallet address
+			args.push("--host".to_string()); args.push(ip.to_string());                     // IP Address
+			args.push("--rpc-port".to_string()); args.push(rpc.to_string());                // RPC Port
+			args.push("--zmq-port".to_string()); args.push(zmq.to_string());                // ZMQ Port
+			args.push("--data-api".to_string()); args.push(api_path.display().to_string()); // API Path
+			args.push("--local-api".to_string()); // Enable API
+			args.push("--no-color".to_string());  // Remove color escape sequences, Gupax terminal can't parse it :(
+			args.push("--mini".to_string());      // P2Pool Mini
 
 		// [Advanced]
 		} else {
@@ -622,30 +633,44 @@ impl Helper {
 	#[tokio::main]
 	async fn spawn_p2pool_watchdog(process: Arc<Mutex<Process>>, pub_api: Arc<Mutex<PubP2poolApi>>, priv_api: Arc<Mutex<PrivP2poolApi>>, args: Vec<String>, path: std::path::PathBuf) {
 		// 1. Create command
-		let mut child = tokio::process::Command::new(path)
+		let child = Arc::new(Mutex::new(tokio::process::Command::new(path)
 			.args(args)
 			.stdout(Stdio::piped())
 			.stderr(Stdio::piped())
 			.stdin(Stdio::piped())
-			.spawn().unwrap();
+			.spawn().unwrap()));
 
-		// 2. Set start time
-		let now = Instant::now();
-		process.lock().unwrap().start = now;
-		process.lock().unwrap().uptime = HumanTime::into_human(now.elapsed());
+        // 2. Set process state
+        let mut lock = process.lock().unwrap();
+        lock.state = ProcessState::Alive;
+        lock.signal = ProcessSignal::None;
+        lock.start = Instant::now();
+        lock.child = Some(Arc::clone(&child));
+		lock.stdin = Some(child.lock().unwrap().stdin.take().unwrap());
+		drop(lock);
 
 		// 3. Spawn STDOUT/STDERR thread
+		let process_clone = Arc::clone(&process);
 		thread::spawn(move || {
-			Self::read_stdout_stderr(&process, child.stdout.take().unwrap(), child.stderr.take().unwrap());
+			Self::read_stdout_stderr(process_clone);
 		});
 
 		// 4. Loop forever as watchdog until process dies
 		loop {
 			// a. Watch user SIGNAL
+			match process.lock().unwrap().signal {
+				ProcessSignal::Stop    => {},
+				ProcessSignal::Restart => {},
+				_ => {},
+			}
 			// b. Create STDIN task
+			if !process.lock().unwrap().input.is_empty() { /* process it */ }
 			// c. Create API task
+			let async_file_read = { /* tokio async file read job */ };
 			// d. Execute async tasks
-			// e. Sleep (900ms)
+			tokio::join![/* jobs */];
+			// f. Sleep (900ms)
+			std::thread::sleep(MILLI_900);
 		}
 	}
 
diff --git a/src/main.rs b/src/main.rs
index 56ede18..ba279f8 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1018,14 +1018,18 @@ impl eframe::App for App {
 								if ui.add_sized([width, height], Button::new("⟲")).on_hover_text("Restart P2Pool").clicked() { self.p2pool = false; }
 								if ui.add_sized([width, height], Button::new("⏹")).on_hover_text("Stop P2Pool").clicked() { self.p2pool = false; }
 								ui.add_enabled_ui(false, |ui| {
-									ui.add_sized([width, height], Button::new("⏺")).on_hover_text("Start P2Pool");
+									if ui.add_sized([width, height], Button::new("⏺")).on_hover_text("Start P2Pool").clicked() {
+										Helper::spawn_p2pool(&self.helper, &self.state.p2pool, self.state.gupax.absolute_p2pool_path.clone());
+									}
 								});
 							} else {
 								ui.add_enabled_ui(false, |ui| {
 									ui.add_sized([width, height], Button::new("⟲")).on_hover_text("Restart P2Pool");
 									ui.add_sized([width, height], Button::new("⏹")).on_hover_text("Stop P2Pool");
 								});
-								if ui.add_sized([width, height], Button::new("⏺")).on_hover_text("Start P2Pool").clicked() { self.p2pool = true; }
+								if ui.add_sized([width, height], Button::new("⏺")).on_hover_text("Start P2Pool").clicked() {
+									Helper::spawn_p2pool(&self.helper, &self.state.p2pool, self.state.gupax.absolute_p2pool_path.clone());
+								}
 							}
 						});
 					},