diff --git a/src/capture.rs b/src/capture.rs index fcfa5a7..cf09507 100644 --- a/src/capture.rs +++ b/src/capture.rs @@ -165,9 +165,12 @@ async fn do_capture( r = InputCapture::new(backend) => r?, _ = wait_for_termination(request_rx) => return Ok(()), }; - event_tx - .send(ICaptureEvent::CaptureEnabled) - .expect("channel closed"); + + let _capture_guard = DropGuard::new( + event_tx, + ICaptureEvent::CaptureEnabled, + ICaptureEvent::CaptureDisabled, + ); let clients = service.client_manager.active_clients(); let clients = clients.iter().copied().map(|handle| { @@ -190,17 +193,8 @@ async fn do_capture( let res = do_capture_session(active, &mut capture, conn, event_tx, request_rx, service).await; // FIXME replace with async drop when stabilized - let res1 = capture.terminate().await; - - // handle errors - res?; - res1?; - - event_tx - .send(ICaptureEvent::CaptureDisabled) - .expect("channel closed"); - - Ok(()) + capture.terminate().await?; + res } async fn do_capture_session( @@ -411,3 +405,24 @@ async fn wait_for_termination(rx: &mut Receiver) { } } } + +struct DropGuard<'a, T> { + tx: &'a Sender, + on_drop: Option, +} + +impl<'a, T> DropGuard<'a, T> { + fn new(tx: &'a Sender, on_new: T, on_drop: T) -> Self { + tx.send(on_new).expect("channel closed"); + let on_drop = Some(on_drop); + Self { tx, on_drop } + } +} + +impl<'a, T> Drop for DropGuard<'a, T> { + fn drop(&mut self) { + self.tx + .send(self.on_drop.take().expect("item")) + .expect("channel closed"); + } +} diff --git a/src/emulation.rs b/src/emulation.rs index f55e74e..c07367b 100644 --- a/src/emulation.rs +++ b/src/emulation.rs @@ -282,9 +282,13 @@ impl EmulationProxy { // allow termination event while requesting input emulation _ = wait_for_termination(request_rx) => return Ok(()), }; - event_tx - .send(EmulationEvent::EmulationEnabled) - .expect("channel closed"); + + // used to send enabled and disabled events + let _emulation_guard = DropGuard::new( + &event_tx, + EmulationEvent::EmulationEnabled, + EmulationEvent::EmulationDisabled, + ); // create active handles for &handle in handles.values() { @@ -297,10 +301,6 @@ impl EmulationProxy { let res = Self::do_emulation_session(&mut emulation, handles, next_id, request_rx).await; // FIXME replace with async drop when stabilized emulation.terminate().await; - - event_tx - .send(EmulationEvent::EmulationDisabled) - .expect("channel closed"); res } @@ -372,3 +372,24 @@ async fn wait_for_termination(rx: &mut Receiver) { } } } + +struct DropGuard<'a, T> { + tx: &'a Sender, + on_drop: Option, +} + +impl<'a, T> DropGuard<'a, T> { + fn new(tx: &'a Sender, on_new: T, on_drop: T) -> Self { + tx.send(on_new).expect("channel closed"); + let on_drop = Some(on_drop); + Self { tx, on_drop } + } +} + +impl<'a, T> Drop for DropGuard<'a, T> { + fn drop(&mut self) { + self.tx + .send(self.on_drop.take().expect("item")) + .expect("channel closed"); + } +}