From eb10f874e8b31f4b6542b2a7276a24dd672f080d Mon Sep 17 00:00:00 2001 From: koekeishiya Date: Wed, 22 Jan 2025 22:37:09 +0100 Subject: [PATCH] #2522 fix issue that could cause a crash --- CHANGELOG.md | 1 + src/process_manager.c | 1 + src/workspace.h | 1 + src/workspace.m | 18 ++++++++++++++++-- 4 files changed, 19 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d7f52bb6..848f60f4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm - Config *global setting* `split_type` is now categorized as a *space setting* instead [#2479](https://github.com/koekeishiya/yabai/issues/2479) - Additional options `x-axis` and `y-axis` can now be used with `config auto_balance` command [#190](https://github.com/koekeishiya/yabai/issues/190) - Minor adjustment to screen-padding and window-gap [#2502](https://github.com/koekeishiya/yabai/issues/2502) +- Fix issue that could cause a crash when a newly launched application terminates rapidly during/after launch [#2522](https://github.com/koekeishiya/yabai/issues/2522) ## [7.1.5] - 2024-11-01 ### Changed diff --git a/src/process_manager.c b/src/process_manager.c index 9d3fa42a..a0c0d6ed 100644 --- a/src/process_manager.c +++ b/src/process_manager.c @@ -103,6 +103,7 @@ static PROCESS_EVENT_HANDLER(process_handler) __atomic_store_n(&process->terminated, true, __ATOMIC_RELEASE); process_manager_remove_process(pm, &psn); + workspace_application_unobserve(g_workspace_context, process); __asm__ __volatile__ ("" ::: "memory"); event_loop_post(&g_event_loop, APPLICATION_TERMINATED, process, 0); diff --git a/src/workspace.h b/src/workspace.h index eb8d81e3..9693cf8d 100644 --- a/src/workspace.h +++ b/src/workspace.h @@ -25,6 +25,7 @@ static inline bool workspace_is_macos_##name(void) \ struct process; void *workspace_application_create_running_ns_application(struct process *process); void workspace_application_destroy_running_ns_application(void *context, struct process *process); +void workspace_application_unobserve(void *context, struct process *process); bool workspace_application_is_observable(struct process *process); bool workspace_application_is_finished_launching(struct process *process); void workspace_application_observe_finished_launching(void *context, struct process *process); diff --git a/src/workspace.m b/src/workspace.m index 0f6beeca..cab2179e 100644 --- a/src/workspace.m +++ b/src/workspace.m @@ -86,6 +86,20 @@ void workspace_application_observe_activation_policy(void *context, struct proce } } +void workspace_application_unobserve(void *ws_context, struct process *process) +{ + NSRunningApplication *application = __atomic_load_n(&process->ns_application, __ATOMIC_RELAXED); + if (application) { + @try { + [application removeObserver:ws_context forKeyPath:@"activationPolicy" context:process]; + } @catch (NSException * __unused exception) {} + + @try { + [application removeObserver:ws_context forKeyPath:@"finishedLaunching" context:process]; + } @catch (NSException * __unused exception) {} + } +} + bool workspace_application_is_observable(struct process *process) { NSRunningApplication *application = __atomic_load_n(&process->ns_application, __ATOMIC_RELAXED); @@ -196,7 +210,7 @@ - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(N { if ([keyPath isEqualToString:@"activationPolicy"]) { struct process *process = context; - assert(!process->terminated); + if (process->terminated) return; id result = [change objectForKey:NSKeyValueChangeNewKey]; if ([result intValue] != process->policy) { @@ -221,7 +235,7 @@ - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(N if ([keyPath isEqualToString:@"finishedLaunching"]) { struct process *process = context; - assert(!process->terminated); + if (process->terminated) return; id result = [change objectForKey:NSKeyValueChangeNewKey]; if ([result intValue] == 1) {