Explorar el Código

reap the exit statuses from 'onevent' child processes

William R. Fraser hace 6 años
padre
commit
eaac599ce3
Se han modificado 3 ficheros con 39 adiciones y 6 borrados
  1. 21 0
      src/child_wait_future.rs
  2. 13 1
      src/main.rs
  3. 5 5
      src/player_event_handler.rs

+ 21 - 0
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<Async<Self::Item>, Self::Error> {
+        match self.child.try_wait() {
+            Ok(Some(status)) => Ok(Async::Ready(status)),
+            Ok(None) => Ok(Async::NotReady),
+            Err(e) => Err(e),
+        }
+    }
+}

+ 13 - 1
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);
                     }
                 }
             }

+ 5 - 5
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<Child> {
     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<Child> {
     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)
 }