From eaac599ce33c8d1b19804ddbef0c7ddebaa2421a Mon Sep 17 00:00:00 2001 From: "William R. Fraser" Date: Tue, 16 Oct 2018 00:24:33 -0700 Subject: [PATCH 1/2] reap the exit statuses from 'onevent' child processes --- src/child_wait_future.rs | 21 +++++++++++++++++++++ src/main.rs | 14 +++++++++++++- src/player_event_handler.rs | 10 +++++----- 3 files changed, 39 insertions(+), 6 deletions(-) create mode 100644 src/child_wait_future.rs diff --git a/src/child_wait_future.rs b/src/child_wait_future.rs new file mode 100644 index 00000000..8a05c677 --- /dev/null +++ b/src/child_wait_future.rs @@ -0,0 +1,21 @@ +use futures::{Async, Future}; +use std::io; +use std::process::{Child, ExitStatus}; + +/// A future that resolves to a child process's exit status once it exits. +pub struct ChildWaitFuture { + pub child: Child, +} + +impl Future for ChildWaitFuture { + type Item = ExitStatus; + type Error = io::Error; + + fn poll(&mut self) -> Result, Self::Error> { + match self.child.try_wait() { + Ok(Some(status)) => Ok(Async::Ready(status)), + Ok(None) => Ok(Async::NotReady), + Err(e) => Err(e), + } + } +} diff --git a/src/main.rs b/src/main.rs index a18d7b5c..8e5442eb 100644 --- a/src/main.rs +++ b/src/main.rs @@ -39,6 +39,9 @@ use librespot::playback::config::{Bitrate, PlayerConfig}; use librespot::playback::mixer::{self, Mixer}; use librespot::playback::player::{Player, PlayerEvent}; +mod child_wait_future; +use child_wait_future::ChildWaitFuture; + mod player_event_handler; use player_event_handler::run_program_on_events; @@ -466,7 +469,16 @@ impl Future for Main { if let Some(ref mut player_event_channel) = self.player_event_channel { if let Async::Ready(Some(event)) = player_event_channel.poll().unwrap() { if let Some(ref program) = self.player_event_program { - run_program_on_events(event, program); + let child = run_program_on_events(event, program) + .expect("program failed to start"); + + let wait_future = ChildWaitFuture { child } + .map(|status| if !status.success() { + error!("child exited with status {:?}", status.code()); + }) + .map_err(|e| error!("failed to wait on child process: {}", e)); + + self.handle.spawn(wait_future); } } } diff --git a/src/player_event_handler.rs b/src/player_event_handler.rs index b6a653dd..1d72d182 100644 --- a/src/player_event_handler.rs +++ b/src/player_event_handler.rs @@ -1,18 +1,18 @@ use librespot::playback::player::PlayerEvent; use std::collections::HashMap; -use std::process::Command; +use std::io; +use std::process::{Child, Command}; -fn run_program(program: &str, env_vars: HashMap<&str, String>) { +fn run_program(program: &str, env_vars: HashMap<&str, String>) -> io::Result { let mut v: Vec<&str> = program.split_whitespace().collect(); info!("Running {:?} with environment variables {:?}", v, env_vars); Command::new(&v.remove(0)) .args(&v) .envs(env_vars.iter()) .spawn() - .expect("program failed to start"); } -pub fn run_program_on_events(event: PlayerEvent, onevent: &str) { +pub fn run_program_on_events(event: PlayerEvent, onevent: &str) -> io::Result { let mut env_vars = HashMap::new(); match event { PlayerEvent::Changed { @@ -32,5 +32,5 @@ pub fn run_program_on_events(event: PlayerEvent, onevent: &str) { env_vars.insert("TRACK_ID", track_id.to_base16()); } } - run_program(onevent, env_vars); + run_program(onevent, env_vars) } From 9fa138a116a9b06bdd3440195acedba6c14ed0e4 Mon Sep 17 00:00:00 2001 From: "William R. Fraser" Date: Tue, 16 Oct 2018 02:32:17 -0700 Subject: [PATCH 2/2] implement using tokio-process instead --- Cargo.lock | 75 +++++++++++++++++++++++++++++++++++-- Cargo.toml | 1 + src/child_wait_future.rs | 21 ----------- src/main.rs | 11 ++---- src/player_event_handler.rs | 5 ++- 5 files changed, 79 insertions(+), 34 deletions(-) delete mode 100644 src/child_wait_future.rs diff --git a/Cargo.lock b/Cargo.lock index c1aa626a..da12b203 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -389,6 +389,7 @@ dependencies = [ "serde_json 0.9.10 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-core 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-process 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-signal 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "vergen 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -591,6 +592,17 @@ dependencies = [ "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "mio-named-pipes" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.14 (registry+https://github.com/rust-lang/crates.io-index)", + "miow 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "mio-uds" version = "0.6.4" @@ -611,6 +623,15 @@ dependencies = [ "ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "miow" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "socket2 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "multimap" version = "0.3.0" @@ -782,7 +803,7 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.1.37" +version = "0.1.40" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -980,6 +1001,17 @@ dependencies = [ "ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "socket2" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "syn" version = "0.11.11" @@ -1021,7 +1053,7 @@ dependencies = [ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1048,7 +1080,7 @@ version = "0.1.39" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1104,6 +1136,21 @@ dependencies = [ "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "tokio-process" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.14 (registry+https://github.com/rust-lang/crates.io-index)", + "mio-named-pipes 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-signal 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "tokio-proto" version = "0.1.1" @@ -1156,6 +1203,21 @@ dependencies = [ "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "tokio-signal" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.14 (registry+https://github.com/rust-lang/crates.io-index)", + "mio-uds 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "tokio-tcp" version = "0.1.0" @@ -1453,8 +1515,10 @@ dependencies = [ "checksum memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0f9dc261e2b62d7a622bf416ea3c5245cdd5d9a7fcc428c0d06804dfce1775b3" "checksum mime 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e2e00e17be181010a91dbfefb01660b17311059dc8c7f48b9017677721e732bd" "checksum mio 0.6.14 (registry+https://github.com/rust-lang/crates.io-index)" = "6d771e3ef92d58a8da8df7d6976bfca9371ed1de6619d9d5a5ce5b1f29b85bfe" +"checksum mio-named-pipes 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "f5e374eff525ce1c5b7687c4cef63943e7686524a387933ad27ca7ec43779cb3" "checksum mio-uds 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "1731a873077147b626d89cc6c2a0db6288d607496c5d10c0cfcf3adc697ec673" "checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919" +"checksum miow 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "396aa0f2003d7df8395cb93e09871561ccc3e785f0acb369170e8cc74ddf9226" "checksum multimap 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9223f4774d08e06185e44e555b9a7561243d387bac49c78a6205c42d6975fbf2" "checksum net2 0.2.32 (registry+https://github.com/rust-lang/crates.io-index)" = "9044faf1413a1057267be51b5afba8eb1090bd2231c693664aa1db716fe1eae0" "checksum nix 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "47e49f6982987135c5e9620ab317623e723bd06738fd85377e8d55f57c8b6487" @@ -1477,7 +1541,7 @@ dependencies = [ "checksum quote 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9949cfe66888ffe1d53e6ec9d9f3b70714083854be20fd5e271b232a017401e8" "checksum rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)" = "15a732abf9d20f0ad8eeb6f909bf6868722d9a06e1e50802b6a70351f40b4eb1" "checksum rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "eba5f8cb59cc50ed56be8880a5c7b496bfd9bd26394e176bc67884094145c2c5" -"checksum redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "0d92eecebad22b767915e4d529f89f28ee96dbbf5a4810d2b844373f136417fd" +"checksum redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "c214e91d3ecf43e9a4e41e578973adeb14b474f2bee858742d127af75a0112b1" "checksum regex 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "aec3f58d903a7d2a9dc2bf0e41a746f4530e0cab6b615494e058f67a3ef947fb" "checksum regex-syntax 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "bd90079345f4a4c3409214734ae220fd773c6f2e8a543d07370c6c1c369cfbfb" "checksum relay 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1576e382688d7e9deecea24417e350d3062d97e32e45d70b1cde65994ff1489a" @@ -1503,6 +1567,7 @@ dependencies = [ "checksum slab 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fdeff4cd9ecff59ec7e3744cbca73dfe5ac35c2aedb2cfba8a1c715a18912e9d" "checksum smallvec 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4c8cbcd6df1e117c2210e13ab5109635ad68a929fcbb8964dc965b76cb5ee013" "checksum socket2 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "36b4896961171cd3317c7e9603d88f379f8c6e45342212235d356496680c68fd" +"checksum socket2 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "06dc9f86ee48652b7c80f3d254e3b9accb67a928c562c64d10d7b016d3d98dab" "checksum syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad" "checksum syn 0.13.4 (registry+https://github.com/rust-lang/crates.io-index)" = "90d5efaad92a0f96c629ae16302cc9591915930fd49ff0dcc6b4cde146782397" "checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6" @@ -1515,10 +1580,12 @@ dependencies = [ "checksum tokio-core 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)" = "aeeffbbb94209023feaef3c196a41cbcdafa06b4a6f893f68779bb5e53796f71" "checksum tokio-executor 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8cac2a7883ff3567e9d66bb09100d09b33d90311feca0206c7ca034bc0c55113" "checksum tokio-io 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "6af9eb326f64b2d6b68438e1953341e00ab3cf54de7e35d92bfc73af8555313a" +"checksum tokio-process 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0832648d1ff7ca42c06ca45dc76797b92c56500de828e33c77276fa1449947b6" "checksum tokio-proto 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8fbb47ae81353c63c487030659494b295f6cb6576242f907f203473b191b0389" "checksum tokio-reactor 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b3cedc8e5af5131dc3423ffa4f877cce78ad25259a9a62de0613735a13ebc64b" "checksum tokio-service 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "24da22d077e0f15f55162bdbdc661228c1581892f52074fb242678d015b45162" "checksum tokio-signal 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e8f46863230f9a05cf52d173721ec391b9c5782a2465f593029922b8782b9ffe" +"checksum tokio-signal 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "b6893092932264944edee8486d54b578c7098bea794aedaf9bd7947b49e6b7bf" "checksum tokio-tcp 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ec9b094851aadd2caf83ba3ad8e8c4ce65a42104f7b94d9e6550023f0407853f" "checksum tokio-threadpool 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bf3d05cdd6a78005e535d2b27c21521bdf91fbb321027a62d8e178929d18966d" "checksum tokio-timer 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "29a89e4ad0c8f1e4c9860e605c38c69bfdad3cccd4ea446e58ff588c1c07a397" diff --git a/Cargo.toml b/Cargo.toml index 3af02908..88b59667 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -49,6 +49,7 @@ serde_derive = "0.9.6" serde_json = "0.9.5" tokio-core = "0.1.2" tokio-io = "0.1" +tokio-process = "0.2.2" tokio-signal = "0.1.2" url = "1.7.0" diff --git a/src/child_wait_future.rs b/src/child_wait_future.rs deleted file mode 100644 index 8a05c677..00000000 --- a/src/child_wait_future.rs +++ /dev/null @@ -1,21 +0,0 @@ -use futures::{Async, Future}; -use std::io; -use std::process::{Child, ExitStatus}; - -/// A future that resolves to a child process's exit status once it exits. -pub struct ChildWaitFuture { - pub child: Child, -} - -impl Future for ChildWaitFuture { - type Item = ExitStatus; - type Error = io::Error; - - fn poll(&mut self) -> Result, Self::Error> { - match self.child.try_wait() { - Ok(Some(status)) => Ok(Async::Ready(status)), - Ok(None) => Ok(Async::NotReady), - Err(e) => Err(e), - } - } -} diff --git a/src/main.rs b/src/main.rs index 8e5442eb..36cd1b5d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -8,6 +8,7 @@ extern crate log; extern crate rpassword; extern crate tokio_core; extern crate tokio_io; +extern crate tokio_process; extern crate tokio_signal; extern crate url; @@ -39,9 +40,6 @@ use librespot::playback::config::{Bitrate, PlayerConfig}; use librespot::playback::mixer::{self, Mixer}; use librespot::playback::player::{Player, PlayerEvent}; -mod child_wait_future; -use child_wait_future::ChildWaitFuture; - mod player_event_handler; use player_event_handler::run_program_on_events; @@ -470,15 +468,14 @@ impl Future for Main { if let Async::Ready(Some(event)) = player_event_channel.poll().unwrap() { if let Some(ref program) = self.player_event_program { let child = run_program_on_events(event, program) - .expect("program failed to start"); - - let wait_future = ChildWaitFuture { child } + .expect("program failed to start") .map(|status| if !status.success() { error!("child exited with status {:?}", status.code()); }) .map_err(|e| error!("failed to wait on child process: {}", e)); - self.handle.spawn(wait_future); + self.handle.spawn(child); + } } } diff --git a/src/player_event_handler.rs b/src/player_event_handler.rs index 1d72d182..23c02313 100644 --- a/src/player_event_handler.rs +++ b/src/player_event_handler.rs @@ -1,7 +1,8 @@ use librespot::playback::player::PlayerEvent; +use tokio_process::{Child, CommandExt}; use std::collections::HashMap; use std::io; -use std::process::{Child, Command}; +use std::process::Command; fn run_program(program: &str, env_vars: HashMap<&str, String>) -> io::Result { let mut v: Vec<&str> = program.split_whitespace().collect(); @@ -9,7 +10,7 @@ fn run_program(program: &str, env_vars: HashMap<&str, String>) -> io::Result io::Result {