diff --git a/src/qemu.rs b/src/qemu.rs index 4aefc44..da76a7a 100644 --- a/src/qemu.rs +++ b/src/qemu.rs @@ -750,6 +750,16 @@ impl Qemu { let _ = updates.send(Output::Command(line)); }; + // Set read timeout to None so we can block indefinitely in case the VM + // is having a hard time, like being overloaded. See #40. + // But reset it back to the old value when we're done. + let old_timeout = qga.read_timeout()?; + scopeguard::defer! { + // Restore old timeout + let _ = qga.set_read_timeout(old_timeout); + } + qga.set_read_timeout(None)?; + let output_stream = connect_to_uds(&self.command_sock) .context("Failed to connect to command output socket")?; diff --git a/src/qga.rs b/src/qga.rs index 526e004..374233b 100644 --- a/src/qga.rs +++ b/src/qga.rs @@ -99,6 +99,21 @@ impl QgaWrapper { bail!("Timed out waiting for QGA connection"); } + /// Set the read timeout of the inner UnixStream. + /// + /// If the provided value is [`None`], then [`read`] calls will block + /// indefinitely. An [`Err`] is returned if the zero [`Duration`] is passed to this + /// method. + pub fn set_read_timeout(&self, timeout: Option) -> Result<()> { + self.stream.set_read_timeout(timeout)?; + Ok(()) + } + + /// Returns the read timeout of the inner UnixStream. + pub fn read_timeout(&self) -> Result> { + Ok(self.stream.read_timeout()?) + } + /// Run a command inside the guest pub fn guest_exec( &self,