Rockbox open source high quality audio player as a Music Player Daemon
mpris rockbox mpd libadwaita audio rust zig deno
2
fork

Configure Feed

Select the types of activity you want to include in your feed.

Reuse Tokio runtimes and raise FD limit

Introduce OnceLock-shared Tokio runtimes (controls, MPD) to avoid
creating a
new runtime per thread. Replace ephemeral runtime creation with reusable
accessors, use blocking_lock for server fs_cache, and switch misplaced
println!/eprintln! diagnostics to tracing::error!. On Unix, raise
RLIMIT_NOFILE (capped at 4096) early in parse_args.

+52 -21
+18
crates/cli/src/lib.rs
··· 76 76 unsafe { libc::_exit(0) }; 77 77 } 78 78 79 + #[cfg(unix)] 80 + fn raise_fd_limit() { 81 + unsafe { 82 + let mut rlim: libc::rlimit = std::mem::zeroed(); 83 + if libc::getrlimit(libc::RLIMIT_NOFILE, &mut rlim) == 0 { 84 + // Raise to 4096 or the hard limit, whichever is lower 85 + let target = 4096_u64.min(rlim.rlim_max); 86 + if rlim.rlim_cur < target { 87 + rlim.rlim_cur = target; 88 + libc::setrlimit(libc::RLIMIT_NOFILE, &rlim); 89 + } 90 + } 91 + } 92 + } 93 + 79 94 #[no_mangle] 80 95 pub extern "C" fn parse_args(argc: usize, argv: *const *const u8) -> i32 { 96 + #[cfg(unix)] 97 + raise_fd_limit(); 98 + 81 99 let subscriber = tracing_subscriber::fmt() 82 100 .with_writer(std::io::stderr) 83 101 .with_env_filter(
+15 -13
crates/controls/src/lib.rs
··· 4 4 }; 5 5 use std::env; 6 6 use std::sync::atomic::{AtomicBool, Ordering}; 7 - use std::sync::{mpsc, Arc}; 7 + use std::sync::{mpsc, Arc, OnceLock}; 8 8 use std::time::Duration; 9 9 use tonic::transport::Channel; 10 + 11 + static CONTROLS_RUNTIME: OnceLock<tokio::runtime::Runtime> = OnceLock::new(); 12 + 13 + fn controls_rt() -> &'static tokio::runtime::Runtime { 14 + CONTROLS_RUNTIME.get_or_init(|| { 15 + tokio::runtime::Runtime::new().expect("failed to create controls runtime") 16 + }) 17 + } 10 18 use winit::application::ApplicationHandler; 11 19 use winit::event::WindowEvent; 12 20 use winit::event_loop::{ActiveEventLoop, ControlFlow, EventLoop}; ··· 139 147 let sender = command_sender.clone(); 140 148 let playing_state = Arc::clone(&is_playing); 141 149 std::thread::spawn(move || { 142 - let runtime = tokio::runtime::Runtime::new().unwrap(); 143 - match runtime.block_on(spawn_metadata_update_task(sender.clone(), playing_state)) { 144 - Ok(_) => println!("Metadata update task completed"), 145 - Err(e) => eprintln!("Metadata update task failed: {}", e), 150 + if let Err(e) = controls_rt().block_on(spawn_metadata_update_task(sender.clone(), playing_state)) { 151 + tracing::error!("Metadata update task failed: {}", e); 146 152 } 147 153 }); 148 154 149 155 let sender = command_sender.clone(); 150 156 std::thread::spawn(move || { 151 - let runtime = tokio::runtime::Runtime::new().unwrap(); 152 - match runtime.block_on(spawn_event_handler_task( 157 + if let Err(e) = controls_rt().block_on(spawn_event_handler_task( 153 158 sender.clone(), 154 159 media_event_receiver, 155 160 )) { 156 - Ok(()) => println!("Event handler task completed"), 157 - Err(e) => eprintln!("Event handler task failed: {}", e), 161 + tracing::error!("Event handler task failed: {}", e); 158 162 } 159 163 }); 160 164 161 165 let sender = command_sender.clone(); 162 166 let playing_state = Arc::clone(&is_playing); 163 167 std::thread::spawn(move || { 164 - let runtime = tokio::runtime::Runtime::new().unwrap(); 165 - match runtime.block_on(spawn_status_update_task(sender.clone(), playing_state)) { 166 - Ok(_) => println!("Status update task completed"), 167 - Err(e) => eprintln!("Status update task failed: {}", e), 168 + if let Err(e) = controls_rt().block_on(spawn_status_update_task(sender.clone(), playing_state)) { 169 + tracing::error!("Status update task failed: {}", e); 168 170 } 169 171 }); 170 172
+18 -6
crates/mpd/src/lib.rs
··· 46 46 }; 47 47 use rockbox_sys::types::user_settings::UserSettings; 48 48 use sqlx::{Pool, Sqlite}; 49 - use std::{env, sync::Arc, thread, time::Duration}; 49 + use std::{ 50 + env, 51 + sync::{Arc, OnceLock}, 52 + thread, 53 + time::Duration, 54 + }; 50 55 use tokio::{ 51 56 io::{AsyncReadExt, AsyncWriteExt}, 52 57 net::{TcpListener, TcpStream}, ··· 55 60 use tokio_stream::StreamExt; 56 61 use tonic::transport::Channel; 57 62 use tracing::{debug, warn}; 63 + 64 + static MPD_RUNTIME: OnceLock<tokio::runtime::Runtime> = OnceLock::new(); 65 + 66 + fn mpd_rt() -> &'static tokio::runtime::Runtime { 67 + MPD_RUNTIME 68 + .get_or_init(|| tokio::runtime::Runtime::new().expect("failed to create MPD runtime")) 69 + } 58 70 59 71 pub mod consts; 60 72 pub mod dir; ··· 333 345 let another_cloned_ctx = ctx.clone(); 334 346 335 347 thread::spawn(move || { 336 - let rt = tokio::runtime::Runtime::new().unwrap(); 348 + let rt = mpd_rt(); 337 349 loop { 338 350 let mut current_settings = rt.block_on(another_cloned_ctx.current_settings.lock()); 339 351 *current_settings = rockbox_sys::settings::get_global_settings(); ··· 344 356 345 357 thread::spawn(move || { 346 358 let mut subscription = SimpleBroker::<Track>::subscribe(); 347 - let rt = tokio::runtime::Runtime::new().unwrap(); 359 + let rt = mpd_rt(); 348 360 349 361 while let Some(track) = rt.block_on(subscription.next()) { 350 362 let mut current_track = rt.block_on(ctx.current_track.lock()); ··· 361 373 362 374 thread::spawn(move || { 363 375 let mut subscription = SimpleBroker::<Playlist>::subscribe(); 364 - let rt = tokio::runtime::Runtime::new().unwrap(); 376 + let rt = mpd_rt(); 365 377 366 378 while let Some(playlist) = rt.block_on(subscription.next()) { 367 379 let mut current_playlist = rt.block_on(ctx_clone.current_playlist.lock()); ··· 385 397 386 398 thread::spawn(move || { 387 399 let mut subscription = SimpleBroker::<AudioStatus>::subscribe(); 388 - let rt = tokio::runtime::Runtime::new().unwrap(); 400 + let rt = mpd_rt(); 389 401 390 402 while let Some(status) = rt.block_on(subscription.next()) { 391 403 let mut playback_status = rt.block_on(another_ctx.playback_status.lock()); ··· 409 421 let ctx_clone = ctx.clone(); 410 422 thread::spawn(move || { 411 423 let mut ctx = ctx_clone.clone(); 412 - let rt = tokio::runtime::Runtime::new().unwrap(); 424 + let rt = mpd_rt(); 413 425 rt.block_on(async { 414 426 let response = ctx 415 427 .system
+1 -2
crates/server/src/cache.rs
··· 9 9 let fs_cache = ctx.fs_cache.clone(); 10 10 let path = path.to_string(); 11 11 thread::spawn(move || { 12 - let rt = tokio::runtime::Runtime::new().unwrap(); 13 - let mut fs_cache = rt.block_on(fs_cache.lock()); 12 + let mut fs_cache = fs_cache.blocking_lock(); 14 13 let mut entries = vec![]; 15 14 16 15 for file in fs::read_dir(&path)? {