Fix `Failed to load environment variables` error message after self-update on Linux (#46367)

Martin Pool created

Closes #46365

The behavior I'm trying to handle here is documented in
https://man7.org/linux/man-pages/man5/proc_pid_exe.5.html.

[@merlinz01

](https://github.com/zed-industries/zed/issues/46365#issuecomment-3723996684)
points to some other alternatives but they don't seem necessary or
justified here.

# Testing

I've manually replaced the binary of a process running this build, to
simulate an update, and then opened a new tree and I don't see the error
message.

I don't know if there's a reasonable way to unit-test this? Let me know.
It seems like it would require using something like rusty-fork to spawn
a specific binary for the test, which I don't think I see already in the
Zed tree and perhaps it would be overkill to add just for this?


Release Notes:

- Fixed "Failed to load environment variables" after applying an update

Change summary

crates/util/src/util.rs | 13 ++++++++++++-
1 file changed, 12 insertions(+), 1 deletion(-)

Detailed changes

crates/util/src/util.rs 🔗

@@ -304,8 +304,19 @@ fn load_shell_from_passwd() -> Result<()> {
 
 /// Returns a shell escaped path for the current zed executable
 pub fn get_shell_safe_zed_path(shell_kind: shell::ShellKind) -> anyhow::Result<String> {
-    let zed_path =
+    let mut zed_path =
         std::env::current_exe().context("Failed to determine current zed executable path.")?;
+    if cfg!(target_os = "linux")
+        && !zed_path.is_file()
+        && let Some(truncated) = zed_path
+            .clone()
+            .file_name()
+            .and_then(|s| s.to_str())
+            .and_then(|n| n.strip_suffix(" (deleted)"))
+    {
+        // Might have been deleted during update; let's use the new binary if there is one.
+        zed_path.set_file_name(truncated);
+    }
 
     zed_path
         .try_shell_safe(shell_kind)