From 477699f8add168819f058e7a1533c6d1a160850c Mon Sep 17 00:00:00 2001 From: Alexander Lyon Date: Fri, 5 May 2023 12:30:50 +0100 Subject: [PATCH 1/8] make sure to log a message depending on the close reason --- crates/turborepo-lib/src/commands/daemon.rs | 21 +++++++++++++++++++-- crates/turborepo-lib/src/daemon/client.rs | 7 ++++++- crates/turborepo-lib/src/daemon/mod.rs | 2 +- 3 files changed, 26 insertions(+), 4 deletions(-) diff --git a/crates/turborepo-lib/src/commands/daemon.rs b/crates/turborepo-lib/src/commands/daemon.rs index d5171b803cba3..e4df475999d84 100644 --- a/crates/turborepo-lib/src/commands/daemon.rs +++ b/crates/turborepo-lib/src/commands/daemon.rs @@ -1,11 +1,13 @@ use std::{path::PathBuf, time::Duration}; +use pidlock::PidlockError::AlreadyOwned; +use tracing::{trace, warn}; use turbopath::{AbsoluteSystemPathBuf, RelativeSystemPathBuf}; use super::CommandBase; use crate::{ cli::DaemonCommand, - daemon::{DaemonConnector, DaemonError}, + daemon::{endpoint::SocketOpenError, CloseReason, DaemonConnector, DaemonError}, tracing::TurboSubscriber, }; @@ -101,7 +103,22 @@ pub async fn daemon_server( .map(|d| Duration::from_nanos(d as u64))?; let server = crate::daemon::DaemonServer::new(base, timeout, log_file)?; - server.serve().await; + let reason = server.serve().await; + + match reason { + CloseReason::SocketOpenError(SocketOpenError::LockError(AlreadyOwned)) => { + warn!("daemon already running"); + } + CloseReason::SocketOpenError(e) => return Err(e.into()), + CloseReason::Interrupt + | CloseReason::ServerClosed + | CloseReason::WatcherClosed + | CloseReason::Timeout + | CloseReason::Shutdown => { + // these are all ok, just exit + trace!("shutting down daemon: {:?}", reason); + } + }; Ok(()) } diff --git a/crates/turborepo-lib/src/daemon/client.rs b/crates/turborepo-lib/src/daemon/client.rs index 9442d4ebae7a2..0f0afc78b688f 100644 --- a/crates/turborepo-lib/src/daemon/client.rs +++ b/crates/turborepo-lib/src/daemon/client.rs @@ -3,7 +3,10 @@ use tonic::{Code, Status}; use tracing::info; use self::proto::turbod_client::TurbodClient; -use super::connector::{DaemonConnector, DaemonConnectorError}; +use super::{ + connector::{DaemonConnector, DaemonConnectorError}, + endpoint::SocketOpenError, +}; use crate::get_version; pub mod proto { @@ -123,6 +126,8 @@ pub enum DaemonError { /// The server was connected but is now unavailable. #[error("server is unavailable")] Unavailable, + #[error("error opening socket: {0}")] + SocketOpen(#[from] SocketOpenError), /// The server is running a different version of turborepo. #[error("version mismatch")] VersionMismatch, diff --git a/crates/turborepo-lib/src/daemon/mod.rs b/crates/turborepo-lib/src/daemon/mod.rs index 3dcb85e6100f0..eda508fb8908d 100644 --- a/crates/turborepo-lib/src/daemon/mod.rs +++ b/crates/turborepo-lib/src/daemon/mod.rs @@ -7,7 +7,7 @@ mod server; pub use client::{DaemonClient, DaemonError}; pub use connector::DaemonConnector; -pub use server::DaemonServer; +pub use server::{CloseReason, DaemonServer}; pub(crate) mod proto { tonic::include_proto!("turbodprotocol"); From 9f939efe03d24831636b030ff53bc574eeb64257 Mon Sep 17 00:00:00 2001 From: Alexander Lyon Date: Fri, 5 May 2023 13:14:37 +0100 Subject: [PATCH 2/8] add integration test for expected messages from lockfile errors --- crates/pidlock/src/lib.rs | 2 +- crates/turborepo-lib/src/daemon/endpoint.rs | 7 +++++-- turborepo-tests/helpers/setup.sh | 1 + turborepo-tests/integration/tests/daemon.t | 13 +++++++++++++ 4 files changed, 20 insertions(+), 3 deletions(-) create mode 100644 turborepo-tests/integration/tests/daemon.t diff --git a/crates/pidlock/src/lib.rs b/crates/pidlock/src/lib.rs index 012560e4e1fd8..86b007dc4dd2d 100644 --- a/crates/pidlock/src/lib.rs +++ b/crates/pidlock/src/lib.rs @@ -12,7 +12,7 @@ use log::warn; #[derive(Debug, thiserror::Error, PartialEq)] pub enum PidlockError { /// A lock already exists - #[error("lock exists at {0}")] + #[error("lock exists at \"{0}\", please remove it")] LockExists(PathBuf), /// An operation was attempted in the wrong state, e.g. releasing before /// acquiring. diff --git a/crates/turborepo-lib/src/daemon/endpoint.rs b/crates/turborepo-lib/src/daemon/endpoint.rs index 6fbb70062797d..40d3afa7226ab 100644 --- a/crates/turborepo-lib/src/daemon/endpoint.rs +++ b/crates/turborepo-lib/src/daemon/endpoint.rs @@ -10,9 +10,12 @@ use turbopath::{AbsoluteSystemPathBuf, RelativeSystemPathBuf}; #[derive(thiserror::Error, Debug)] pub enum SocketOpenError { + /// Returned when there is an IO error opening the socket, + /// such as the path being too long, or the path being + /// invalid. #[error("IO error: {0}")] Io(#[from] std::io::Error), - #[error("pidlock error")] + #[error("pidlock error: {0}")] LockError(#[from] pidlock::PidlockError), } @@ -43,7 +46,7 @@ pub async fn listen_socket( lock.acquire()?; std::fs::remove_file(&sock_path).ok(); - debug!("pidlock acquired as {}", pid_path); + debug!("pidlock acquired at {}", pid_path); debug!("listening on socket at {}", sock_path); #[cfg(unix)] diff --git a/turborepo-tests/helpers/setup.sh b/turborepo-tests/helpers/setup.sh index 59090ce8b8dbd..041b750912e80 100755 --- a/turborepo-tests/helpers/setup.sh +++ b/turborepo-tests/helpers/setup.sh @@ -5,3 +5,4 @@ ROOT_DIR="${THIS_DIR}/../.." TURBO=${ROOT_DIR}/target/debug/turbo VERSION=${ROOT_DIR}/version.txt +TMPDIR=$(mktemp -d) diff --git a/turborepo-tests/integration/tests/daemon.t b/turborepo-tests/integration/tests/daemon.t new file mode 100644 index 0000000000000..4f680b8321880 --- /dev/null +++ b/turborepo-tests/integration/tests/daemon.t @@ -0,0 +1,13 @@ +Setup + $ . ${TESTDIR}/../../helpers/setup.sh + +The daemon exits when there is a stale pid file + $ ${TURBO} daemon & sleep 1 && kill $! && ${TURBO} daemon + WARN stale pid file at ".+" (re) + ERROR error opening socket: pidlock error: lock exists at ".+", please remove it (re) + /bin/bash: line 4: .+ (re) + [1] + +A message is printed when the daemon is running already + $ rm -r ${TMPDIR}/turbod; ${TURBO} daemon & (export PID=$!; sleep 1 && ${TURBO} daemon && kill $PID && kill $PID && kill $PID) + WARN daemon already running From 9e557bd6349dac3a8cf27e4024442d856c7fda33 Mon Sep 17 00:00:00 2001 From: Alexander Lyon Date: Fri, 5 May 2023 15:46:57 +0100 Subject: [PATCH 3/8] add tracing-chrome behind a feature flag --- Cargo.lock | 16 ++++++++++++++-- crates/turborepo-lib/Cargo.toml | 1 + crates/turborepo-lib/src/tracing.rs | 21 +++++++++++++++++++-- crates/turborepo/Cargo.toml | 1 + 4 files changed, 35 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7dd9af35c7852..aa4a6d875675c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8171,6 +8171,17 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "tracing-chrome" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "496b3cd5447f7ff527bbbf19b071ad542a000adf297d4127078b4dfdb931f41a" +dependencies = [ + "serde_json", + "tracing-core", + "tracing-subscriber", +] + [[package]] name = "tracing-core" version = "0.1.30" @@ -9137,6 +9148,7 @@ dependencies = [ "tower", "tracing", "tracing-appender", + "tracing-chrome", "tracing-subscriber", "tracing-test", "turbo-updater", @@ -9181,8 +9193,8 @@ version = "1.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97fee6b57c6a41524a810daee9286c02d7752c4253064d0b05472833a438f675" dependencies = [ - "cfg-if 0.1.10", - "rand 0.4.6", + "cfg-if 1.0.0", + "rand 0.8.5", "static_assertions", ] diff --git a/crates/turborepo-lib/Cargo.toml b/crates/turborepo-lib/Cargo.toml index 52d07442065c6..597b44671a6f2 100644 --- a/crates/turborepo-lib/Cargo.toml +++ b/crates/turborepo-lib/Cargo.toml @@ -85,6 +85,7 @@ node-semver = "2.1.0" owo-colors.workspace = true regex.workspace = true tracing-appender = "0.2.2" +tracing-chrome = { version = "0.7.1", optional = true } tracing-subscriber = { version = "0.3.17", features = ["env-filter"] } tracing.workspace = true turbo-updater = { workspace = true } diff --git a/crates/turborepo-lib/src/tracing.rs b/crates/turborepo-lib/src/tracing.rs index efa32ec76f526..5e7dcfc61ac42 100644 --- a/crates/turborepo-lib/src/tracing.rs +++ b/crates/turborepo-lib/src/tracing.rs @@ -5,7 +5,7 @@ use owo_colors::{ colors::{Black, Default, Red, Yellow}, Color, OwoColorize, }; -use tracing::{field::Visit, metadata::LevelFilter, Event, Level, Subscriber}; +use tracing::{field::Visit, metadata::LevelFilter, trace, Event, Level, Subscriber}; use tracing_appender::{ non_blocking::{NonBlocking, WorkerGuard}, rolling::RollingFileAppender, @@ -46,6 +46,9 @@ pub struct TurboSubscriber { /// The non-blocking file logger only continues to log while this guard is /// held. We keep it here so that it doesn't get dropped. guard: Mutex>, + + #[cfg(feature = "tracing-chrome")] + chrome_guard: tracing_chrome::FlushGuard, } impl TurboSubscriber { @@ -90,19 +93,33 @@ impl TurboSubscriber { // we set this layer to None to start with, effectively disabling it let (logrotate, update) = reload::Layer::new(Option::::None); - Registry::default().with(stdout).with(logrotate).init(); + let registry = Registry::default().with(stdout).with(logrotate); + + #[cfg(feature = "tracing-chrome")] + let (registry, chrome_guard) = { + let (chrome_layer, guard) = tracing_chrome::ChromeLayerBuilder::new() + .file("./tracing.json") + .build(); + (registry.with(chrome_layer), guard) + }; + + registry.init(); Self { update, guard: Mutex::new(None), + #[cfg(feature = "tracing-chrome")] + chrome_guard, } } /// Enables daemon logging with the specified rotation settings. /// /// Daemon logging uses the standard tracing formatter. + #[tracing::instrument(skip(self))] pub fn set_daemon_logger(&self, appender: RollingFileAppender) -> Result<(), Error> { let (file_writer, guard) = tracing_appender::non_blocking(appender); + trace!("created non-blocking file writer"); let layer = tracing_subscriber::fmt::layer().with_writer(file_writer); diff --git a/crates/turborepo/Cargo.toml b/crates/turborepo/Cargo.toml index 93abb30ae2e06..1fe87e8dfae76 100644 --- a/crates/turborepo/Cargo.toml +++ b/crates/turborepo/Cargo.toml @@ -13,6 +13,7 @@ default = ["rustls-tls"] native-tls = ["turborepo-lib/native-tls"] rustls-tls = ["turborepo-lib/rustls-tls"] http = ["turborepo-lib/http"] +tracing-chrome = ["turborepo-lib/tracing-chrome"] # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [build-dependencies] From 3d103940d06158143bf1ea6e996bd4ed30ea616d Mon Sep 17 00:00:00 2001 From: Alexander Lyon Date: Fri, 5 May 2023 15:56:19 +0100 Subject: [PATCH 4/8] add trace and instrumentation directives --- crates/turborepo-lib/src/commands/daemon.rs | 1 + crates/turborepo-lib/src/daemon/endpoint.rs | 4 +++- crates/turborepo-lib/src/daemon/server.rs | 2 ++ crates/turborepo-lib/src/globwatcher/mod.rs | 2 ++ 4 files changed, 8 insertions(+), 1 deletion(-) diff --git a/crates/turborepo-lib/src/commands/daemon.rs b/crates/turborepo-lib/src/commands/daemon.rs index e4df475999d84..09108756bd023 100644 --- a/crates/turborepo-lib/src/commands/daemon.rs +++ b/crates/turborepo-lib/src/commands/daemon.rs @@ -67,6 +67,7 @@ pub async fn daemon_client(command: &DaemonCommand, base: &CommandBase) -> Resul Ok(()) } +#[tracing::instrument(skip(base, logging), fields(repo_root = %base.repo_root))] pub async fn daemon_server( base: &CommandBase, idle_time: &String, diff --git a/crates/turborepo-lib/src/daemon/endpoint.rs b/crates/turborepo-lib/src/daemon/endpoint.rs index 40d3afa7226ab..5ed4423ed09e1 100644 --- a/crates/turborepo-lib/src/daemon/endpoint.rs +++ b/crates/turborepo-lib/src/daemon/endpoint.rs @@ -5,7 +5,7 @@ use std::{io::ErrorKind, sync::atomic::Ordering, time::Duration}; use futures::Stream; use tokio::io::{AsyncRead, AsyncWrite}; use tonic::transport::server::Connected; -use tracing::debug; +use tracing::{debug, trace}; use turbopath::{AbsoluteSystemPathBuf, RelativeSystemPathBuf}; #[derive(thiserror::Error, Debug)] @@ -28,6 +28,7 @@ const WINDOWS_POLL_DURATION: Duration = Duration::from_millis(1); /// /// note: the running param is used by the windows /// code path to shut down the non-blocking polling +#[tracing::instrument] pub async fn listen_socket( path: AbsoluteSystemPathBuf, #[allow(unused)] running: Arc, @@ -42,6 +43,7 @@ pub async fn listen_socket( let sock_path = path.join_relative(RelativeSystemPathBuf::new("turbod.sock").unwrap()); let mut lock = pidlock::Pidlock::new(pid_path.as_path().to_owned()); + trace!("acquiring pidlock"); // this will fail if the pid is already owned lock.acquire()?; std::fs::remove_file(&sock_path).ok(); diff --git a/crates/turborepo-lib/src/daemon/server.rs b/crates/turborepo-lib/src/daemon/server.rs index 954ec362b36a7..7ddd0ed84c466 100644 --- a/crates/turborepo-lib/src/daemon/server.rs +++ b/crates/turborepo-lib/src/daemon/server.rs @@ -71,6 +71,7 @@ pub enum CloseReason { } impl DaemonServer { + #[tracing::instrument(skip(base), fields(repo_root = %base.repo_root))] pub fn new( base: &CommandBase, timeout: Duration, @@ -112,6 +113,7 @@ impl Drop for DaemonServer { impl DaemonServer { /// Serve the daemon server, while also watching for filesystem changes. + #[tracing::instrument(skip(self))] pub async fn serve(mut self) -> CloseReason { let stop = StopSource::new(); let watcher = self.watcher.clone(); diff --git a/crates/turborepo-lib/src/globwatcher/mod.rs b/crates/turborepo-lib/src/globwatcher/mod.rs index 8072c9a3a80c0..cc3863a1158c5 100644 --- a/crates/turborepo-lib/src/globwatcher/mod.rs +++ b/crates/turborepo-lib/src/globwatcher/mod.rs @@ -46,6 +46,7 @@ pub struct GlobSet { } impl HashGlobWatcher { + #[tracing::instrument] pub fn new( relative_to: AbsoluteSystemPathBuf, flush_folder: PathBuf, @@ -64,6 +65,7 @@ impl HashGlobWatcher { impl HashGlobWatcher { /// Watches a given path, using the flush_folder as temporary storage to /// make sure that file events are handled in the appropriate order. + #[tracing::instrument(skip(self, token))] pub async fn watch(&self, token: StopToken) { let start_globs = { let lock = self.hash_globs.lock().expect("only fails if poisoned"); From 0171c9e42247a42648a0367fad34ac4629918b56 Mon Sep 17 00:00:00 2001 From: Alexander Lyon Date: Fri, 5 May 2023 15:56:51 +0100 Subject: [PATCH 5/8] move flush watching out of the critical path --- crates/globwatch/src/lib.rs | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/crates/globwatch/src/lib.rs b/crates/globwatch/src/lib.rs index 3ba0fcc670125..0d4ea2bc2892c 100644 --- a/crates/globwatch/src/lib.rs +++ b/crates/globwatch/src/lib.rs @@ -62,7 +62,7 @@ impl GlobWatcher { std::fs::create_dir_all(&flush_dir).ok(); let flush_dir = flush_dir.canonicalize()?; - let mut watcher = notify::recommended_watcher(move |event: Result| { + let watcher = notify::recommended_watcher(move |event: Result| { let span = span!(tracing::Level::TRACE, "watcher"); let _ = span.enter(); @@ -83,10 +83,25 @@ impl GlobWatcher { } })?; - watcher.watch(flush_dir.as_path(), notify::RecursiveMode::Recursive)?; - let watcher = Arc::new(Mutex::new(watcher)); + // registering to watch this directory takes a few ms, + // so we just fire and forget a thread to do it in the + // background, to cut our startup time in half. + let flush = watcher.clone(); + let path = flush_dir.as_path().to_owned(); + tokio::task::spawn_blocking(move || { + if let Err(e) = flush + .lock() + .expect("only fails if poisoned") + .watch(&path, notify::RecursiveMode::Recursive) + { + warn!("failed to watch flush dir: {}", e); + } else { + trace!("watching flush dir: {:?}", path); + } + }); + Ok(( Self { flush_dir, From 67bc954a30c9b8e96e58b745d2cef2ea19f9f7bf Mon Sep 17 00:00:00 2001 From: Alexander Lyon Date: Fri, 5 May 2023 17:52:41 +0100 Subject: [PATCH 6/8] attempt to throttle spawning lots of daemons before the first is ready --- cli/internal/daemon/connector/connector.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/cli/internal/daemon/connector/connector.go b/cli/internal/daemon/connector/connector.go index f8742d317807b..3df2025d88609 100644 --- a/cli/internal/daemon/connector/connector.go +++ b/cli/internal/daemon/connector/connector.go @@ -128,6 +128,7 @@ const ( _maxAttempts = 10 _shutdownTimeout = 1 * time.Second _socketPollTimeout = 1 * time.Second + _notReadyTimeout = 3 * time.Millisecond ) // killLiveServer tells a running server to shut down. This method is also responsible @@ -254,8 +255,11 @@ func (c *Connector) connectInternal(ctx context.Context) (*Client, error) { } // Loops back around and tries again. } else if errors.Is(err, errUnavailable) { - // close the client, see if we can kill the stale daemon + // The rust daemon will open the socket a few ms before it's ready to accept connections. + // If we get here, we know that the socket exists, but the server isn't ready yet. + // We'll wait a few ms and try again. c.Logger.Debug("server not ready yet") + time.Sleep(_notReadyTimeout) } else if err != nil { // Some other error occurred, close the client and // report the error to the user From fe95ba26f944f96e75be74c89b74e649e822061c Mon Sep 17 00:00:00 2001 From: Greg Soltis Date: Fri, 5 May 2023 14:57:46 -0700 Subject: [PATCH 7/8] Allow better daemon testing by skipping inference when we start the daemon --- cli/internal/daemon/connector/connector.go | 2 +- crates/turborepo-lib/src/daemon/connector.rs | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/cli/internal/daemon/connector/connector.go b/cli/internal/daemon/connector/connector.go index 3df2025d88609..b5d967a0c7969 100644 --- a/cli/internal/daemon/connector/connector.go +++ b/cli/internal/daemon/connector/connector.go @@ -375,7 +375,7 @@ func (c *Connector) waitForSocket() error { // startDaemon starts the daemon and returns the pid for the new process func (c *Connector) startDaemon() (int, error) { - args := []string{"daemon"} + args := []string{"--skip-infer", "daemon"} if c.Opts.ServerTimeout != 0 { args = append(args, fmt.Sprintf("--idle-time=%v", c.Opts.ServerTimeout.String())) } diff --git a/crates/turborepo-lib/src/daemon/connector.rs b/crates/turborepo-lib/src/daemon/connector.rs index 6e0f8dc19b45d..99a8cca1a2496 100644 --- a/crates/turborepo-lib/src/daemon/connector.rs +++ b/crates/turborepo-lib/src/daemon/connector.rs @@ -148,6 +148,7 @@ impl DaemonConnector { // this creates a new process group for the given command // in a cross platform way, directing all output to /dev/null let mut group = tokio::process::Command::new(binary_path) + .arg("--skip-infer") .arg("daemon") .stderr(Stdio::null()) .stdout(Stdio::null()) From b21af0ec60900eef0ce7f632644a5849edca6b6e Mon Sep 17 00:00:00 2001 From: Greg Soltis Date: Mon, 8 May 2023 12:49:47 -0700 Subject: [PATCH 8/8] Move flaky integration test to rust unit test --- crates/turborepo-lib/src/daemon/endpoint.rs | 66 +++++++++++++++++++++ turborepo-tests/integration/tests/daemon.t | 13 ---- 2 files changed, 66 insertions(+), 13 deletions(-) delete mode 100644 turborepo-tests/integration/tests/daemon.t diff --git a/crates/turborepo-lib/src/daemon/endpoint.rs b/crates/turborepo-lib/src/daemon/endpoint.rs index 5ed4423ed09e1..019a2af135858 100644 --- a/crates/turborepo-lib/src/daemon/endpoint.rs +++ b/crates/turborepo-lib/src/daemon/endpoint.rs @@ -172,3 +172,69 @@ impl Connected for UdsWindowsStream { type ConnectInfo = (); fn connect_info(&self) -> Self::ConnectInfo {} } + +#[cfg(test)] +mod test { + use std::{ + assert_matches::assert_matches, + path::Path, + process::Command, + sync::{atomic::AtomicBool, Arc}, + }; + + use pidlock::PidlockError; + use turbopath::AbsoluteSystemPathBuf; + + use super::listen_socket; + use crate::daemon::endpoint::SocketOpenError; + + fn pid_path(tmp_path: &Path) -> AbsoluteSystemPathBuf { + AbsoluteSystemPathBuf::new(tmp_path.join("turbod.pid")).unwrap() + } + + #[tokio::test] + async fn test_stale_pid() { + let tmp_dir = tempfile::tempdir().unwrap(); + let tmp_path = tmp_dir.path().to_owned(); + let pid_path = pid_path(&tmp_path); + // A pid that will never be running and is guaranteed not to be us + pid_path.create_with_contents("100000").unwrap(); + + let running = Arc::new(AtomicBool::new(true)); + let result = listen_socket(pid_path, running).await; + + // Note: PidLock doesn't implement Debug, so we can't unwrap_err() + if let Err(err) = result { + assert_matches!(err, SocketOpenError::LockError(PidlockError::LockExists(_))); + } else { + panic!("expected an error") + } + } + + #[tokio::test] + async fn test_existing_process() { + let tmp_dir = tempfile::tempdir().unwrap(); + let tmp_path = tmp_dir.path().to_owned(); + let pid_path = pid_path(&tmp_path); + + #[cfg(windows)] + let node_bin = "node.exe"; + #[cfg(not(windows))] + let node_bin = "node"; + + let child = Command::new(node_bin).spawn().unwrap(); + pid_path + .create_with_contents(format!("{}", child.id()).as_ref()) + .unwrap(); + + let running = Arc::new(AtomicBool::new(true)); + let result = listen_socket(pid_path, running).await; + + // Note: PidLock doesn't implement Debug, so we can't unwrap_err() + if let Err(err) = result { + assert_matches!(err, SocketOpenError::LockError(PidlockError::LockExists(_))); + } else { + panic!("expected an error") + } + } +} diff --git a/turborepo-tests/integration/tests/daemon.t b/turborepo-tests/integration/tests/daemon.t deleted file mode 100644 index 4f680b8321880..0000000000000 --- a/turborepo-tests/integration/tests/daemon.t +++ /dev/null @@ -1,13 +0,0 @@ -Setup - $ . ${TESTDIR}/../../helpers/setup.sh - -The daemon exits when there is a stale pid file - $ ${TURBO} daemon & sleep 1 && kill $! && ${TURBO} daemon - WARN stale pid file at ".+" (re) - ERROR error opening socket: pidlock error: lock exists at ".+", please remove it (re) - /bin/bash: line 4: .+ (re) - [1] - -A message is printed when the daemon is running already - $ rm -r ${TMPDIR}/turbod; ${TURBO} daemon & (export PID=$!; sleep 1 && ${TURBO} daemon && kill $PID && kill $PID && kill $PID) - WARN daemon already running