mirror of
https://github.com/outbackdingo/firezone.git
synced 2026-01-27 10:18:54 +00:00
fix(gui-client): keep the IPC service running even if the GUI quits during sign-in (#5451)
Closes #5450 Now the entire `Handler::run` function is allowed to fail, similar to a web request handler failing in a web server. Previously we only allowed the Handler to fail if it was idle, waiting on incoming IPC requests. Now it can fail even if it's working with connlib and about to send over IPC. I replicated this on my Windows 11 VM in Parallels and the fix works fine there. Should be the same bug and same fix in Linux.
This commit is contained in:
@@ -447,10 +447,7 @@ async fn ipc_listen() -> Result<std::convert::Infallible> {
|
||||
.next_client_split()
|
||||
.await
|
||||
.context("Failed to wait for incoming IPC connection from a GUI")?;
|
||||
Handler::new(rx, tx)?
|
||||
.run()
|
||||
.await
|
||||
.context("Error while handling IPC client")?;
|
||||
Handler::new(rx, tx)?.run().await;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -488,14 +485,18 @@ impl Handler {
|
||||
})
|
||||
}
|
||||
|
||||
async fn run(&mut self) -> Result<()> {
|
||||
// Infallible so that we only give up on an IPC client explicitly
|
||||
async fn run(&mut self) {
|
||||
loop {
|
||||
let event = {
|
||||
// This borrows `self` so we must drop it before handling the `Event`.
|
||||
let cb = pin!(self.cb_rx.recv());
|
||||
match future::select(self.ipc_rx.next(), cb).await {
|
||||
future::Either::Left((Some(Ok(x)), _)) => Event::Ipc(x),
|
||||
future::Either::Left((Some(Err(error)), _)) => Err(error)?,
|
||||
future::Either::Left((Some(Err(error)), _)) => {
|
||||
tracing::error!(?error, "Error while deserializing IPC message");
|
||||
continue;
|
||||
}
|
||||
future::Either::Left((None, _)) => {
|
||||
tracing::info!("IPC client disconnected");
|
||||
break;
|
||||
@@ -508,13 +509,20 @@ impl Handler {
|
||||
}
|
||||
};
|
||||
match event {
|
||||
Event::Callback(x) => self.handle_connlib_cb(x).await?,
|
||||
Event::Ipc(msg) => self
|
||||
.handle_ipc_msg(msg)
|
||||
.context("Error while handling IPC message from client")?,
|
||||
Event::Callback(x) => {
|
||||
if let Err(error) = self.handle_connlib_cb(x).await {
|
||||
tracing::error!(?error, "Error while handling connlib callback");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
Event::Ipc(msg) => {
|
||||
if let Err(error) = self.handle_ipc_msg(msg) {
|
||||
tracing::error!(?error, "Error while handling IPC message from client");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn handle_connlib_cb(&mut self, msg: InternalServerMsg) -> Result<()> {
|
||||
@@ -527,12 +535,18 @@ impl Handler {
|
||||
tracing::info!(?dur, "Connlib started");
|
||||
}
|
||||
}
|
||||
self.ipc_tx.send(&msg).await?
|
||||
self.ipc_tx
|
||||
.send(&msg)
|
||||
.await
|
||||
.context("Error while sending IPC message")?
|
||||
}
|
||||
InternalServerMsg::OnSetInterfaceConfig { ipv4, ipv6, dns } => {
|
||||
self.tun_device.set_ips(ipv4, ipv6).await?;
|
||||
self.dns_controller.set_dns(&dns).await?;
|
||||
self.ipc_tx.send(&IpcServerMsg::OnTunnelReady).await?;
|
||||
self.ipc_tx
|
||||
.send(&IpcServerMsg::OnTunnelReady)
|
||||
.await
|
||||
.context("Error while sending `OnTunnelReady`")?
|
||||
}
|
||||
InternalServerMsg::OnUpdateRoutes { ipv4, ipv6 } => {
|
||||
self.tun_device.set_routes(ipv4, ipv6).await?
|
||||
|
||||
Reference in New Issue
Block a user