fix cli welcome screen (#13474)

Conrad Irwin and Mikayla created

Release Notes:

- Fixed first launch via cli

---------

Co-authored-by: Mikayla <mikayla@zed.dev>

Change summary

Cargo.lock                          |  1 
crates/cli/Cargo.toml               |  1 
crates/cli/src/main.rs              | 49 +++++++++++++++++++-----------
crates/zed/src/zed/open_listener.rs |  3 +
4 files changed, 35 insertions(+), 19 deletions(-)

Detailed changes

Cargo.lock 🔗

@@ -2223,6 +2223,7 @@ dependencies = [
  "fork",
  "ipc-channel",
  "once_cell",
+ "parking_lot",
  "paths",
  "plist",
  "release_channel",

crates/cli/Cargo.toml 🔗

@@ -21,6 +21,7 @@ anyhow.workspace = true
 clap.workspace = true
 ipc-channel = "0.18"
 once_cell.workspace = true
+parking_lot.workspace = true
 paths.workspace = true
 release_channel.workspace = true
 serde.workspace = true

crates/cli/src/main.rs 🔗

@@ -3,10 +3,12 @@
 use anyhow::{Context, Result};
 use clap::Parser;
 use cli::{ipc::IpcOneShotServer, CliRequest, CliResponse, IpcHandshake};
+use parking_lot::Mutex;
 use std::{
     env, fs, io,
     path::{Path, PathBuf},
     process::ExitStatus,
+    sync::Arc,
     thread::{self, JoinHandle},
 };
 use util::paths::PathLikeWithPosition;
@@ -123,26 +125,34 @@ fn main() -> Result<()> {
         None
     };
 
-    let sender: JoinHandle<anyhow::Result<()>> = thread::spawn(move || {
-        let (_, handshake) = server.accept().context("Handshake after Zed spawn")?;
-        let (tx, rx) = (handshake.requests, handshake.responses);
-        tx.send(CliRequest::Open {
-            paths,
-            wait: args.wait,
-            open_new_workspace,
-            dev_server_token: args.dev_server_token,
-        })?;
-
-        while let Ok(response) = rx.recv() {
-            match response {
-                CliResponse::Ping => {}
-                CliResponse::Stdout { message } => println!("{message}"),
-                CliResponse::Stderr { message } => eprintln!("{message}"),
-                CliResponse::Exit { status } => std::process::exit(status),
+    let exit_status = Arc::new(Mutex::new(None));
+
+    let sender: JoinHandle<anyhow::Result<()>> = thread::spawn({
+        let exit_status = exit_status.clone();
+        move || {
+            let (_, handshake) = server.accept().context("Handshake after Zed spawn")?;
+            let (tx, rx) = (handshake.requests, handshake.responses);
+            tx.send(CliRequest::Open {
+                paths,
+                wait: args.wait,
+                open_new_workspace,
+                dev_server_token: args.dev_server_token,
+            })?;
+
+            while let Ok(response) = rx.recv() {
+                match response {
+                    CliResponse::Ping => {}
+                    CliResponse::Stdout { message } => println!("{message}"),
+                    CliResponse::Stderr { message } => eprintln!("{message}"),
+                    CliResponse::Exit { status } => {
+                        exit_status.lock().replace(status);
+                        return Ok(());
+                    }
+                }
             }
-        }
 
-        Ok(())
+            Ok(())
+        }
     });
 
     if args.foreground {
@@ -152,6 +162,9 @@ fn main() -> Result<()> {
         sender.join().unwrap()?;
     }
 
+    if let Some(exit_status) = exit_status.lock().take() {
+        std::process::exit(exit_status);
+    }
     Ok(())
 }
 

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

@@ -398,7 +398,8 @@ pub async fn handle_cli_connection(
                         }
                     }
                 } else if matches!(KEY_VALUE_STORE.read_kvp(FIRST_OPEN), Ok(None)) {
-                    cx.update(|cx| show_welcome_view(app_state, cx)).log_err();
+                    cx.update(|cx| show_welcome_view(app_state, cx).detach())
+                        .log_err();
                 } else {
                     cx.update(|cx| {
                         workspace::open_new(app_state, cx, |workspace, cx| {