fix: program stuck in infinite loop on config error

This commit is contained in:
zawz 2023-08-28 16:12:37 +02:00
parent 1a5bb96e41
commit 9b97114dcd
5 changed files with 31 additions and 18 deletions

View file

@ -15,10 +15,10 @@ lazy_static = "1.4"
clap = { version = "4.1", features = ["derive"] } clap = { version = "4.1", features = ["derive"] }
thiserror = "1.0" thiserror = "1.0"
enum-display-derive = "0.1" enum-display-derive = "0.1"
queues = "1.1.0" queues = "1.1"
duration-str = { version = "0.5.1", features = ["serde"] } duration-str = { version = "0.5", features = ["serde"] }
signal-hook = "0.3.17" signal-hook = "0.3"
[target.'cfg(target_os = "linux")'.dependencies] [target.'cfg(target_os = "linux")'.dependencies]
alsa = "0.7.0" alsa = "0.7"
libc = "0.2.21" libc = "0.2.21"

View file

@ -44,7 +44,8 @@ impl<'a> EventMap<'a> {
for ev in v { for ev in v {
if ev.match_value(event) { if ev.match_value(event) {
for r in &ev.run { for r in &ev.run {
r.run(event.make_env(ev.remap.as_ref(), ev.float )?.to_map(r.envconf.as_ref()))?; let env = event.make_env(ev.remap.as_ref(), ev.float )?.to_map(r.envconf.as_ref());
r.run(env)?;
} }
} }
} }

View file

@ -24,13 +24,16 @@ fn main() {
loop { loop {
match run_file(&c.map_file) { match run_file(&c.map_file) {
Ok(_) => (), Ok(_) => (),
Err(err) => println!("Error: {}", err) Err(err) => {
eprintln!("Error: {}", err);
std::process::exit(1);
}
} }
} }
} }
fn run_file(filepath: &Path) -> Result<(), Error> { fn run_file(filepath: &Path) -> Result<(), Error> {
println!("Load file {}", filepath.to_str().unwrap()); println!("Load file {}", filepath.to_str().unwrap_or("<unknown>"));
let dat = std::fs::read( filepath )?; let dat = std::fs::read( filepath )?;
let conf = Config::try_from(&dat[..])?; let conf = Config::try_from(&dat[..])?;
run::run_config(&conf) run::run_config(&conf)

View file

@ -202,6 +202,7 @@ where T: MidiInputHandler + Send
// parking signal for runner, true = stop // parking signal for runner, true = stop
let (pts,prs) = mpsc::channel::<bool>(); let (pts,prs) = mpsc::channel::<bool>();
// event queue populated by the main thread and consumed by the exec thread
let evq = Arc::new(Mutex::new(CircularBuffer::<EventBuf>::new(conf.queue_length))); let evq = Arc::new(Mutex::new(CircularBuffer::<EventBuf>::new(conf.queue_length)));
// background execution loop // background execution loop
@ -222,6 +223,7 @@ where T: MidiInputHandler + Send
} }
}; };
eventmap.run_event(&ev.as_event()).unwrap_or_else(|e| eprintln!("ERROR: error on run: {}", e) ); eventmap.run_event(&ev.as_event()).unwrap_or_else(|e| eprintln!("ERROR: error on run: {}", e) );
// wait until interval has been reached
let elapsed_time = start.elapsed(); let elapsed_time = start.elapsed();
if elapsed_time < conf.interval { if elapsed_time < conf.interval {
thread::sleep(conf.interval - elapsed_time); thread::sleep(conf.interval - elapsed_time);

View file

@ -11,7 +11,7 @@ use crate::config::{Config,DeviceConfig};
use crate::eventmap::EventMap; use crate::eventmap::EventMap;
type DeviceRunItem<'a> = (&'a DeviceConfig, EventMap<'a>, Option<Arc<Mutex<(u32, u32)>>>); type DeviceRunItem<'a> = (&'a DeviceConfig, EventMap<'a>, Option<Arc<Mutex<(u32, u32)>>>);
type DeviceRunResult<'a> =(thread::ScopedJoinHandle<'a, ()>, mpsc::Sender<bool>); type DeviceRunResult<'a> =(thread::ScopedJoinHandle<'a, Result<(), Error>>, mpsc::Sender<bool>);
pub fn cross_shell(cmd: &str) -> Vec<String> { pub fn cross_shell(cmd: &str) -> Vec<String> {
if cfg!(target_os = "windows") { if cfg!(target_os = "windows") {
@ -54,7 +54,7 @@ pub fn run_config(conf: &Config) -> Result<(), Error> {
}); });
thread::scope(|s| -> Result<(), Error> { thread::scope(|s| -> Result<(), Error> {
let mut threads: Vec<(thread::ScopedJoinHandle<'_, ()>, mpsc::Sender<bool>)> = Vec::new(); let mut threads: Vec<DeviceRunResult> = Vec::new();
let ports = input.ports()?; let ports = input.ports()?;
for p in ports { for p in ports {
if let Some(v) = try_connect_process(&input, s, &p, &cfevmap)? { threads.push(v) } if let Some(v) = try_connect_process(&input, s, &p, &cfevmap)? { threads.push(v) }
@ -77,7 +77,7 @@ pub fn run_config(conf: &Config) -> Result<(), Error> {
event_thread.join().unwrap()?; event_thread.join().unwrap()?;
for (thread,ss) in threads { for (thread,ss) in threads {
let _ = ss.send(true); let _ = ss.send(true);
thread.join().unwrap(); let _ = thread.join().unwrap().map_err(|e| eprintln!("WARN: error in thread: {}", e));
} }
Ok(()) Ok(())
})?; })?;
@ -91,29 +91,36 @@ fn try_connect_process<'a>(
cfevmap: &'a[DeviceRunItem<'a>], cfevmap: &'a[DeviceRunItem<'a>],
) )
-> Result<Option<DeviceRunResult<'a>>, Error> { -> Result<Option<DeviceRunResult<'a>>, Error> {
for (dev, eventmap, m) in cfevmap { for (dev, eventmap, counter) in cfevmap {
if let Some(m) = m { // device counter is full
if let Some(m) = counter {
let m = m.lock().unwrap(); let m = m.lock().unwrap();
if m.0 >= m.1 { if m.0 >= m.1 {
continue; continue;
} }
} }
if let Some(mut c) = input.try_connect(p.clone(), PortFilter::from(*dev))? { if let Some(mut c) = input.try_connect(p.clone(), PortFilter::from(*dev))? {
if let Some(m) = m { // increase device counter
if let Some(m) = counter {
let mut m = m.lock().unwrap(); let mut m = m.lock().unwrap();
m.0 += 1; m.0 += 1;
} }
// stop signal channel
let (sts,srs) = mpsc::channel::<bool>(); let (sts,srs) = mpsc::channel::<bool>();
let mm = counter.as_ref().map(Arc::clone);
let nsts = sts.clone(); let nsts = sts.clone();
let mm = m.as_ref().map(Arc::clone); let t = s.spawn( move || -> Result<(), Error> {
let t = s.spawn( move || { dev.run_connect()?;
dev.run_connect().unwrap(); // blocking process
c.run(dev, eventmap, (nsts,srs)).unwrap(); c.run(dev, eventmap, (nsts,srs))?;
// decrease device counter
if let Some(m) = mm { if let Some(m) = mm {
let mut m = m.lock().unwrap(); let mut m = m.lock().unwrap();
m.0 -= 1; m.0 -= 1;
} }
dev.run_disconnect().unwrap(); dev.run_disconnect()?;
Ok(())
}); });
return Ok(Some((t, sts))); return Ok(Some((t, sts)));
} }