From 9608dabf2bbab1eaa76d578e83bf60bf7ea9db0b Mon Sep 17 00:00:00 2001 From: jecaro Date: Sun, 16 Jul 2023 21:10:12 +0200 Subject: [PATCH] fix deadlock in the server discovery fct recv_from blocks until there is something to read. So if slimserver is started after the message has been sent there is no way any reply can arrive. --- Cargo.lock | 2 +- Cargo.toml | 2 +- src/discover.rs | 14 ++++++++++++-- src/main.rs | 18 +++++++++++++----- 4 files changed, 27 insertions(+), 9 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d51509c..dda4120 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -700,7 +700,7 @@ dependencies = [ [[package]] name = "mprisqueeze" -version = "0.1.2" +version = "0.1.3" dependencies = [ "anyhow", "clap", diff --git a/Cargo.toml b/Cargo.toml index b4d24b9..6c892c1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mprisqueeze" -version = "0.1.2" +version = "0.1.3" authors = ["Jean-Charles Quillet "] edition = "2018" license = "MIT" diff --git a/src/discover.rs b/src/discover.rs index 25d8c63..c4c05e5 100644 --- a/src/discover.rs +++ b/src/discover.rs @@ -7,6 +7,7 @@ use nom::{ sequence::{preceded, tuple}, IResult, }; +use std::io::ErrorKind; use tokio::net::UdpSocket; #[derive(Debug)] @@ -33,9 +34,18 @@ pub async fn discover() -> Result { sock.set_broadcast(true)?; let mut buf = [0; 1024]; - let _ = sock.send_to(&message, "255.255.255.255:3483").await?; + loop { + let _ = sock.send_to(&message, "255.255.255.255:3483").await?; - let _ = sock.recv_from(&mut buf).await?; + match sock.try_recv(&mut buf) { + Err(ref e) if e.kind() == ErrorKind::WouldBlock => { + continue; + } + anything_else => { + break anything_else; + } + } + }?; parse_reply(&buf) .map(|(_, reply)| { diff --git a/src/main.rs b/src/main.rs index 38dede7..fd44e1b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -9,7 +9,7 @@ use tokio::{ pin, process::{Child, Command}, select, - time::sleep, + time::{sleep, timeout}, }; mod discover; mod lms; @@ -25,12 +25,19 @@ struct Options { #[arg(short, long, default_value = "SqueezeLite", help = "Player name")] player_name: String, #[arg( - short, + short = 't', long, default_value_t = 3, help = "Timeout in seconds for squeezelite to be recognized by LMS" )] - timeout: u64, + player_timeout: u64, + #[arg( + short = 'T', + long, + default_value_t = 3, + help = "Timeout in seconds for LMS discovery" + )] + discover_timeout: u64, #[arg( last = true, default_values_t = vec!["squeezelite".to_string(), "-n".to_string(), "{}".to_string()], @@ -105,7 +112,8 @@ async fn main() -> Result<()> { .. } => (hostname.clone(), port), _ => { - let reply = discover().await?; + let reply = + timeout(Duration::from_secs(options.discover_timeout), discover()).await??; (reply.hostname, reply.port) } }; @@ -116,7 +124,7 @@ async fn main() -> Result<()> { let result: Result<()> = (|| async { // wait for the player to be available let (client, mut recv) = LmsClient::new(hostname, port); - wait_for_player(&client, &options.player_name, options.timeout).await?; + wait_for_player(&client, &options.player_name, options.player_timeout).await?; // start the MPRIS server let _connection = start_dbus_server(client, options.player_name).await?;