Skip to content

Commit 1fcbeb5

Browse files
committed
muvm: gracefully disable hidpipe when /dev/input is missing
Treat missing /dev/input as non-fatal, skip hidpipe setup, and avoid starting guest hidpipe when host hidpipe is disabled. Signed-off-by: Zewei Yang <[email protected]>
1 parent ea73c7c commit 1fcbeb5

4 files changed

Lines changed: 44 additions & 23 deletions

File tree

crates/muvm/src/bin/muvm.rs

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -291,6 +291,7 @@ fn main() -> Result<ExitCode> {
291291
}
292292
}
293293

294+
let mut enable_hidpipe = false;
294295
if let Ok(run_path) = env::var("XDG_RUNTIME_DIR") {
295296
let pulse_path = Path::new(&run_path).join("pulse/native");
296297
if pulse_path.exists() {
@@ -309,19 +310,22 @@ fn main() -> Result<ExitCode> {
309310
}
310311

311312
let hidpipe_path = Path::new(&run_path).join("hidpipe");
312-
spawn_hidpipe_server(hidpipe_path.clone()).context("Failed to spawn hidpipe thread")?;
313-
let hidpipe_path = CString::new(
314-
hidpipe_path
315-
.to_str()
316-
.expect("hidpipe_path should not contain invalid UTF-8"),
317-
)
318-
.context("Failed to process `hidpipe` path as it contains NUL character")?;
313+
enable_hidpipe =
314+
spawn_hidpipe_server(hidpipe_path.clone()).context("Failed to spawn hidpipe thread")?;
315+
if enable_hidpipe {
316+
let hidpipe_path = CString::new(
317+
hidpipe_path
318+
.to_str()
319+
.expect("hidpipe_path should not contain invalid UTF-8"),
320+
)
321+
.context("Failed to process `hidpipe` path as it contains NUL character")?;
319322

320-
// SAFETY: `hidpipe_path` is a pointer to a `CString` with long enough lifetime.
321-
let err = unsafe { krun_add_vsock_port(ctx_id, HIDPIPE_SOCKET, hidpipe_path.as_ptr()) };
322-
if err < 0 {
323-
let err = Errno::from_raw_os_error(-err);
324-
return Err(err).context("Failed to configure vsock for hidpipe socket");
323+
// SAFETY: `hidpipe_path` is a pointer to a `CString` with long enough lifetime.
324+
let err = unsafe { krun_add_vsock_port(ctx_id, HIDPIPE_SOCKET, hidpipe_path.as_ptr()) };
325+
if err < 0 {
326+
let err = Errno::from_raw_os_error(-err);
327+
return Err(err).context("Failed to configure vsock for hidpipe socket");
328+
}
325329
}
326330

327331
let socket_dir = Path::new(&run_path).join("krun/socket");
@@ -413,6 +417,7 @@ fn main() -> Result<ExitCode> {
413417
cwd,
414418
init_commands,
415419
user_init_commands: options.user_init_commands,
420+
enable_hidpipe,
416421
};
417422
let mut muvm_config_file = NamedTempFile::new()
418423
.context("Failed to create a temporary file to store the muvm guest config")?;

crates/muvm/src/guest/bin/muvm-guest.rs

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -147,12 +147,16 @@ fn main() -> Result<ExitCode> {
147147
setup_x11_forwarding(run_path, &host_display)?;
148148
}
149149

150-
let uid = options.uid;
151-
thread::spawn(move || {
152-
if catch_unwind(|| start_hidpipe(uid)).is_err() {
153-
eprintln!("hidpipe thread crashed, input device passthrough will no longer function");
154-
}
155-
});
150+
if options.enable_hidpipe {
151+
let uid = options.uid;
152+
thread::spawn(move || {
153+
if catch_unwind(|| start_hidpipe(uid)).is_err() {
154+
eprintln!(
155+
"hidpipe thread crashed, input device passthrough will no longer function"
156+
);
157+
}
158+
});
159+
}
156160

157161
thread::spawn(|| {
158162
if catch_unwind(start_pwbridge).is_err() {

crates/muvm/src/hidpipe_server.rs

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -280,12 +280,18 @@ where
280280
}
281281
}
282282

283-
pub fn spawn_hidpipe_server(socket_path: PathBuf) -> anyhow::Result<()> {
283+
pub fn spawn_hidpipe_server(socket_path: PathBuf) -> anyhow::Result<bool> {
284284
let mut evdevs = EvdevContainer::new();
285285
let epoll = Epoll::new(EpollCreateFlags::empty()).context("Failed to create epoll object")?;
286-
for dir_ent in
287-
fs::read_dir("/dev/input/").context("Failed to read \"/dev/input/\" directory")?
288-
{
286+
let dir_entries = match fs::read_dir("/dev/input/") {
287+
Ok(entries) => entries,
288+
Err(err) if err.kind() == ErrorKind::NotFound => {
289+
debug!("Skipping hidpipe initialization: /dev/input is not present");
290+
return Ok(false);
291+
},
292+
Err(err) => return Err(err).context("Failed to read \"/dev/input/\" directory"),
293+
};
294+
for dir_ent in dir_entries {
289295
let dir_ent = dir_ent.context("Failed to read directory entry")?;
290296
if dir_ent
291297
.file_type()
@@ -321,7 +327,7 @@ pub fn spawn_hidpipe_server(socket_path: PathBuf) -> anyhow::Result<()> {
321327
.unwrap();
322328

323329
thread::spawn(move || run(evdevs, listen_sock, epoll));
324-
Ok(())
330+
Ok(true)
325331
}
326332

327333
fn run(mut evdevs: EvdevContainer, listen_sock: UnixListener, epoll: Epoll) {

crates/muvm/src/utils/launch.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,12 @@ pub struct GuestConfiguration {
4646
pub cwd: PathBuf,
4747
pub init_commands: Vec<PathBuf>,
4848
pub user_init_commands: Vec<PathBuf>,
49+
#[serde(default = "default_true")]
50+
pub enable_hidpipe: bool,
51+
}
52+
53+
fn default_true() -> bool {
54+
true
4955
}
5056

5157
pub const PULSE_SOCKET: u32 = 3333;

0 commit comments

Comments
 (0)