diff --git a/docs/changelog.rst b/docs/changelog.rst index bfc8967a9..d376bed28 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -195,6 +195,9 @@ Detailed list of changes - macOS: Workaround for regression in Tahoe 26.2 that breaks :option:`kitty --detach` (:iss:`9288`) +- macOS: Workaround for yet another Tahoe regression causing macOS to start an + AutoFill helper process and not shut it down on application exit (:iss:`9299`) + 0.44.0 [2025-11-03] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/glfw/cocoa_init.m b/glfw/cocoa_init.m index 6c3bce1d0..e258c3d65 100644 --- a/glfw/cocoa_init.m +++ b/glfw/cocoa_init.m @@ -29,6 +29,7 @@ #include "internal.h" #include "../kitty/monotonic.h" #include // For MAXPATHLEN +#include #include // Needed for _NSGetProgname @@ -417,6 +418,7 @@ - (void)application:(NSApplication *)sender openURLs:(NSArray *)urls } static void *AppearanceObservationContext = &AppearanceObservationContext; +static NSDate *application_finished_launching_at = nil; - (void)applicationDidFinishLaunching:(NSNotification *)notification { @@ -430,6 +432,7 @@ - (void)applicationDidFinishLaunching:(NSNotification *)notification CGDisplayRegisterReconfigurationCallback(display_reconfigured, NULL); _glfwCocoaPostEmptyEvent(); + application_finished_launching_at = [NSDate date]; } GLFWAPI GLFWColorScheme glfwGetCurrentSystemColorTheme(bool query_if_unintialized) { @@ -1009,11 +1012,47 @@ int _glfwPlatformInit(bool *supports_window_occlusion) } // autoreleasepool } +static NSDate* +get_process_start_time(pid_t pid) { + struct kinfo_proc kp; + size_t len = sizeof(kp); + int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, pid }; + + if (sysctl(mib, 4, &kp, &len, NULL, 0) == 0 && len == sizeof(kp)) { + struct timeval start_tv = kp.kp_proc.p_starttime; + time_t start_sec = start_tv.tv_sec; + suseconds_t start_usec = start_tv.tv_usec; + NSTimeInterval t = (NSTimeInterval)start_sec + ((NSTimeInterval)start_usec / 1000000.0); + return [NSDate dateWithTimeIntervalSince1970:t]; + } + return nil; +} void _glfwPlatformTerminate(void) { @autoreleasepool { + // Kill the AutoFill helper process that macOS Tahoe starts and fails to + // shutdown on application exit, see https://github.com/kovidgoyal/kitty/issues/9299 + // Only kill helpers that were launched within a few seconds of this process to + // avoid killing helpers from other processes. This is obviously not robust + // but since Apple cant design its way out of a paper bag, it's the best we + // can do. + if (application_finished_launching_at != nil) { + for (NSRunningApplication *app in [[NSWorkspace sharedWorkspace] runningApplications]) { + if ([app.bundleIdentifier isEqualToString:@"com.apple.SafariPlatformSupport.Helper"] && + [[app.localizedName lowercaseString] containsString:@"autofill (kitty)"]) { + NSDate *st = get_process_start_time(app.processIdentifier); + if (st != nil) { + NSTimeInterval timeDifference = [application_finished_launching_at timeIntervalSinceDate:st]; + [st release]; + if (fabs(timeDifference) <= 5) [app forceTerminate]; + } + } + } + [application_finished_launching_at release]; application_finished_launching_at = nil; + } + _glfwClearDisplayLinks(); if (_glfw.ns.inputSource)