Prevent possible deadlocks when pressing Escape to cancel recordings (#408)
* PRevent possible deadlocks when pressing Escape to cancel recordings * same for sigusr2 --------- Co-authored-by: CJ Pais <cj@cjpais.com>
This commit is contained in:
parent
0a7a1a0aa5
commit
3f401d933a
2 changed files with 50 additions and 35 deletions
|
|
@ -870,25 +870,32 @@ pub fn register_shortcut(app: &AppHandle, binding: ShortcutBinding) -> Result<()
|
|||
action.stop(ah, &binding_id_for_closure, &shortcut_string);
|
||||
}
|
||||
} else {
|
||||
// Toggle mode: toggle on press only
|
||||
if event.state == ShortcutState::Pressed {
|
||||
let toggle_state_manager = ah.state::<ManagedToggleState>();
|
||||
// Determine action and update state while holding the lock,
|
||||
// but RELEASE the lock before calling the action to avoid deadlocks.
|
||||
// (Actions may need to acquire the lock themselves, e.g., cancel_current_operation)
|
||||
let should_start: bool;
|
||||
{
|
||||
let toggle_state_manager = ah.state::<ManagedToggleState>();
|
||||
let mut states = toggle_state_manager
|
||||
.lock()
|
||||
.expect("Failed to lock toggle state manager");
|
||||
|
||||
let mut states = toggle_state_manager.lock().expect("Failed to lock toggle state manager");
|
||||
let is_currently_active = states
|
||||
.active_toggles
|
||||
.entry(binding_id_for_closure.clone())
|
||||
.or_insert(false);
|
||||
|
||||
let is_currently_active = states.active_toggles
|
||||
.entry(binding_id_for_closure.clone())
|
||||
.or_insert(false);
|
||||
should_start = !*is_currently_active;
|
||||
*is_currently_active = should_start;
|
||||
} // Lock released here
|
||||
|
||||
if *is_currently_active {
|
||||
action.stop(
|
||||
ah,
|
||||
&binding_id_for_closure,
|
||||
&shortcut_string,
|
||||
);
|
||||
*is_currently_active = false; // Update state to inactive
|
||||
} else {
|
||||
// Now call the action without holding the lock
|
||||
if should_start {
|
||||
action.start(ah, &binding_id_for_closure, &shortcut_string);
|
||||
*is_currently_active = true; // Update state to active
|
||||
} else {
|
||||
action.stop(ah, &binding_id_for_closure, &shortcut_string);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,32 +25,40 @@ pub fn setup_signal_handler(app_handle: AppHandle, mut signals: Signals) {
|
|||
let shortcut_string = "SIGUSR2";
|
||||
|
||||
if let Some(action) = ACTION_MAP.get(binding_id) {
|
||||
let toggle_state_manager =
|
||||
app_handle_for_signal.state::<ManagedToggleState>();
|
||||
// Determine action and update state while holding the lock,
|
||||
// but RELEASE the lock before calling the action to avoid deadlocks.
|
||||
// (Actions may need to acquire the lock themselves, e.g., cancel_current_operation)
|
||||
let should_start: bool;
|
||||
{
|
||||
let toggle_state_manager =
|
||||
app_handle_for_signal.state::<ManagedToggleState>();
|
||||
|
||||
let mut states = match toggle_state_manager.lock() {
|
||||
Ok(s) => s,
|
||||
Err(e) => {
|
||||
warn!("Failed to lock toggle state manager: {e}");
|
||||
continue;
|
||||
}
|
||||
};
|
||||
let mut states = match toggle_state_manager.lock() {
|
||||
Ok(s) => s,
|
||||
Err(e) => {
|
||||
warn!("Failed to lock toggle state manager: {e}");
|
||||
continue;
|
||||
}
|
||||
};
|
||||
|
||||
let is_currently_active = states
|
||||
.active_toggles
|
||||
.entry(binding_id.to_string())
|
||||
.or_insert(false);
|
||||
let is_currently_active = states
|
||||
.active_toggles
|
||||
.entry(binding_id.to_string())
|
||||
.or_insert(false);
|
||||
|
||||
if *is_currently_active {
|
||||
debug!("SIGUSR2: Stopping transcription (currently active)");
|
||||
action.stop(&app_handle_for_signal, binding_id, shortcut_string);
|
||||
*is_currently_active = false; // Update state to inactive
|
||||
debug!("SIGUSR2: Transcription stopped");
|
||||
} else {
|
||||
debug!("SIGUSR2: Starting transcription (currently inactive)");
|
||||
should_start = !*is_currently_active;
|
||||
*is_currently_active = should_start;
|
||||
} // Lock released here
|
||||
|
||||
// Now call the action without holding the lock
|
||||
if should_start {
|
||||
debug!("SIGUSR2: Starting transcription (was inactive)");
|
||||
action.start(&app_handle_for_signal, binding_id, shortcut_string);
|
||||
*is_currently_active = true; // Update state to active
|
||||
info!("SIGUSR2: Transcription started");
|
||||
} else {
|
||||
debug!("SIGUSR2: Stopping transcription (was active)");
|
||||
action.stop(&app_handle_for_signal, binding_id, shortcut_string);
|
||||
debug!("SIGUSR2: Transcription stopped");
|
||||
}
|
||||
} else {
|
||||
warn!("No action defined in ACTION_MAP for binding ID '{binding_id}'");
|
||||
|
|
|
|||
Loading…
Reference in a new issue