Fix "busy" cursor appearing on startup (#44019)

Closes https://github.com/zed-industries/zed/issues/43910

Release Notes:

- N/A
This commit is contained in:
John Tur
2025-12-02 16:15:18 -05:00
committed by GitHub
parent 23e5477a4c
commit a2ddb0f1cb
3 changed files with 62 additions and 0 deletions

1
Cargo.lock generated
View File

@@ -4184,6 +4184,7 @@ dependencies = [
"serde_json",
"smol",
"system_specs",
"windows 0.61.3",
"zstd 0.11.2+zstd.1.5.2",
]

View File

@@ -23,6 +23,9 @@ zstd.workspace = true
[target.'cfg(target_os = "macos")'.dependencies]
mach2.workspace = true
[target.'cfg(target_os = "windows")'.dependencies]
windows.workspace = true
[lints]
workspace = true

View File

@@ -3,6 +3,8 @@ use log::info;
use minidumper::{Client, LoopAction, MinidumpBinary};
use release_channel::{RELEASE_CHANNEL, ReleaseChannel};
use serde::{Deserialize, Serialize};
#[cfg(not(target_os = "windows"))]
use smol::process::Command;
#[cfg(target_os = "macos")]
@@ -70,11 +72,16 @@ pub async fn init(crash_init: InitCrashHandler) {
// used by the crash handler isn't destroyed correctly which causes it to stay on the file
// system and block further attempts to initialize crash handlers with that socket path.
let socket_name = paths::temp_dir().join(format!("zed-crash-handler-{zed_pid}"));
#[cfg(not(target_os = "windows"))]
let _crash_handler = Command::new(exe)
.arg("--crash-handler")
.arg(&socket_name)
.spawn()
.expect("unable to spawn server process");
#[cfg(target_os = "windows")]
spawn_crash_handler_windows(&exe, &socket_name);
#[cfg(target_os = "linux")]
let server_pid = _crash_handler.id();
info!("spawning crash handler process");
@@ -342,6 +349,57 @@ pub fn panic_hook(info: &PanicHookInfo) {
}
}
#[cfg(target_os = "windows")]
fn spawn_crash_handler_windows(exe: &Path, socket_name: &Path) {
use std::ffi::OsStr;
use std::iter::once;
use std::os::windows::ffi::OsStrExt;
use windows::Win32::System::Threading::{
CreateProcessW, PROCESS_CREATION_FLAGS, PROCESS_INFORMATION, STARTF_FORCEOFFFEEDBACK,
STARTUPINFOW,
};
use windows::core::PWSTR;
let mut command_line: Vec<u16> = OsStr::new(&format!(
"\"{}\" --crash-handler \"{}\"",
exe.display(),
socket_name.display()
))
.encode_wide()
.chain(once(0))
.collect();
let mut startup_info = STARTUPINFOW::default();
startup_info.cb = std::mem::size_of::<STARTUPINFOW>() as u32;
// By default, Windows enables a "busy" cursor when a GUI application is launched.
// This cursor is disabled once the application starts processing window messages.
// Since the crash handler process doesn't process messages, this "busy" cursor stays enabled for a long time.
// Disable the cursor feedback to prevent this from happening.
startup_info.dwFlags = STARTF_FORCEOFFFEEDBACK;
let mut process_info = PROCESS_INFORMATION::default();
unsafe {
CreateProcessW(
None,
Some(PWSTR(command_line.as_mut_ptr())),
None,
None,
false,
PROCESS_CREATION_FLAGS(0),
None,
None,
&startup_info,
&mut process_info,
)
.expect("unable to spawn server process");
windows::Win32::Foundation::CloseHandle(process_info.hProcess).ok();
windows::Win32::Foundation::CloseHandle(process_info.hThread).ok();
}
}
pub fn crash_server(socket: &Path) {
let Ok(mut server) = minidumper::Server::with_name(socket) else {
log::info!("Couldn't create socket, there may already be a running crash server");