linux: Use filesystem based unix socket instead of abstract namespace (#12756)

maan2003 created

Release Notes:

- N/A

fixes: unable to launch multiple zed instances even if the support dirs
are different(example: bwrap based sandboxing)

Change summary

Cargo.lock                          |  1 -
crates/cli/Cargo.toml               |  1 -
crates/cli/src/main.rs              | 13 ++++---------
crates/zed/src/zed/open_listener.rs | 15 ++++++++++-----
4 files changed, 14 insertions(+), 16 deletions(-)

Detailed changes

Cargo.lock 🔗

@@ -2150,7 +2150,6 @@ dependencies = [
  "exec",
  "fork",
  "ipc-channel",
- "libc",
  "once_cell",
  "plist",
  "release_channel",

crates/cli/Cargo.toml 🔗

@@ -19,7 +19,6 @@ path = "src/main.rs"
 [dependencies]
 anyhow.workspace = true
 clap.workspace = true
-libc.workspace = true
 ipc-channel = "0.18"
 once_cell.workspace = true
 release_channel.workspace = true

crates/cli/src/main.rs 🔗

@@ -161,10 +161,7 @@ mod linux {
         env,
         ffi::OsString,
         io,
-        os::{
-            linux::net::SocketAddrExt,
-            unix::net::{SocketAddr, UnixDatagram},
-        },
+        os::unix::net::{SocketAddr, UnixDatagram},
         path::{Path, PathBuf},
         process::{self, ExitStatus},
         thread,
@@ -175,6 +172,7 @@ mod linux {
     use cli::FORCE_CLI_MODE_ENV_VAR_NAME;
     use fork::Fork;
     use once_cell::sync::Lazy;
+    use util::paths;
 
     use crate::{Detect, InstalledApp};
 
@@ -223,12 +221,9 @@ mod linux {
         }
 
         fn launch(&self, ipc_url: String) -> anyhow::Result<()> {
-            let uid: u32 = unsafe { libc::getuid() };
-            let sock_addr =
-                SocketAddr::from_abstract_name(format!("zed-{}-{}", *RELEASE_CHANNEL, uid))?;
-
+            let sock_path = paths::SUPPORT_DIR.join(format!("zed-{}.sock", *RELEASE_CHANNEL));
             let sock = UnixDatagram::unbound()?;
-            if sock.connect_addr(&sock_addr).is_err() {
+            if sock.connect(&sock_path).is_err() {
                 self.boot_background(ipc_url)?;
             } else {
                 sock.send(ipc_url.as_bytes())?;

crates/zed/src/zed/open_listener.rs 🔗

@@ -112,12 +112,17 @@ impl OpenListener {
 #[cfg(target_os = "linux")]
 pub fn listen_for_cli_connections(opener: OpenListener) -> Result<()> {
     use release_channel::RELEASE_CHANNEL_NAME;
-    use std::os::{linux::net::SocketAddrExt, unix::net::SocketAddr, unix::net::UnixDatagram};
+    use std::os::unix::net::UnixDatagram;
+    use util::paths;
 
-    let uid: u32 = unsafe { libc::getuid() };
-    let sock_addr =
-        SocketAddr::from_abstract_name(format!("zed-{}-{}", *RELEASE_CHANNEL_NAME, uid))?;
-    let listener = UnixDatagram::bind_addr(&sock_addr)?;
+    let sock_path = paths::SUPPORT_DIR.join(format!("zed-{}.sock", *RELEASE_CHANNEL_NAME));
+    // remove the socket if the process listening on it has died
+    if let Err(e) = UnixDatagram::unbound()?.connect(&sock_path) {
+        if e.kind() == std::io::ErrorKind::ConnectionRefused {
+            std::fs::remove_file(&sock_path)?;
+        }
+    }
+    let listener = UnixDatagram::bind(&sock_path)?;
     thread::spawn(move || {
         let mut buf = [0u8; 1024];
         while let Ok(len) = listener.recv(&mut buf) {