Always kill PM2 daemon when running site stop --all#2683
Always kill PM2 daemon when running site stop --all#2683
site stop --all#2683Conversation
When no sites are running, the daemon should still be killed to prevent stale processes from persisting, particularly in development where the daemon may retain hardcoded paths to node_modules that become invalid.
site stop --all
epeicher
left a comment
There was a problem hiding this comment.
Thanks for fixing this @gcsecsey! I have been able to reproduce this on trunk by starting Studio and quickly quitting before the sites start. At that point, the pm2 processes are kept there. This is not happening on this branch, so this LGTM! ![]()
| Trunk | This branch |
|---|---|
![]() |
![]() |
There was a problem hiding this comment.
This looks like an npm 10 vs 11 difference. I suggest reverting this file.
@gcsecsey, if you use nvm to manage Node versions, the current .nvmrc file should give you Node 24 and npm 11.
There was a problem hiding this comment.
Is this change required?
I pushed this by mistake, this isn't required.
@gcsecsey, if you use nvm to manage Node versions, the current .nvmrc file should give you Node 24 and npm 11.
Thanks! I also noticed that the npm version is not always 11 for me, and I found that fnm and nvm were conflicting in my zshrc to set the correct node/npm versions. I mainly use fnm, but also needed nvm installed when working on the jetpack repo, and I didn't notice the conflicts for a long time. 😄 Now .nvmrc works as expected for me too.
fredrikekelund
left a comment
There was a problem hiding this comment.
Each workspace has its own node_modules, and when the PM2 daemon was started from one workspace, it retained hardcoded paths to that workspace’s node_modules. When I switched to a different workspace (or the original one was removed/changed), the stale daemon would fail to fork child processes with MODULE_NOT_FOUND errors because those paths no longer existed.
I don't understand how to reproduce this. Could you share the steps to do so, @gcsecsey?
Regardless, I think the change makes sense 👍 site stop --all should always kill the pm2 daemon.
There was a problem hiding this comment.
This looks like an npm 10 vs 11 difference. I suggest reverting this file.
@gcsecsey, if you use nvm to manage Node versions, the current .nvmrc file should give you Node 24 and npm 11.
📊 Performance Test ResultsComparing 02e5e58 vs trunk site-editor
site-startup
Results are median values from multiple test runs. Legend: 🟢 Improvement (faster) | 🔴 Regression (slower) | ⚪ No change (<50ms diff) |
I can't reproduce the original issue anymore either! 🎉 I think reconciling the node version managers solved this issue for me. Now, even on trunk the daemon is consistently stopped after stopping sites, I see no processes in I don't know under what other conditions the daemon could remain running. But I agree it'd make sense to always kill it when stopping all sites. This was roughly the original set of steps I did when first encountering the issue: # Create a new worktree A and build the CLI
cd path/to/studio
git worktree add .tmp/worktree-a trunk
cd .tmp/studio-worktree-a
npm install
npm run cli:build
# Start a site to spawn the PM2 daemon from worktree A
node apps/cli/dist/cli/main.js site start --path ~/Studio/my-wordpress-website
# Stop the site, keeping the daemon alive
node apps/cli/dist/cli/main.js site stop --all
# Remove worktree A
cd path/to/studio
git worktree remove .tmp/worktree-a --force
# Build the CLI in the root
npm install
npm run cli:build
# Try starting a site: the stale daemon fails to fork
node apps/cli/dist/cli/main.js site start --path ~/Studio/my-wordpress-website
# ERROR: MODULE_NOT_FOUND — the daemon still references .tmp/studio-worktree-a/node_modules/... |
@gcsecsey I don't know if it was the original issue, but in |
I can't reproduce that, when I hit
|
|
Please find a video below, it depends on the timing, but I have not been able to reproduce this on this branch CleanShot.2026-03-02.at.13.05.54.mp4 |
Thanks for sharing the video @epeicher, I think this is a more consistently reproducible issue than the one I originally shared. 👍 We also discussed above that it makes sense to kill the process daemon on |
|
The failing E2E tests are unrelated to these changes, I re-triggered the job on Buildkite. |
|
Yeah, conceptually, there's a small window where @gcsecsey, I realize now that I thought you were referring to npm workspaces in your PR description. Makes much more sense now that I understand you were talking about git workspaces. |



Related issues
I ran into an issue while working on Studio from multiple workspaces. Each workspace has its own node_modules, and when the PM2 daemon was started from one workspace, it retained hardcoded paths to that workspace’s node_modules. When I switched to a different workspace (or the original one was removed/changed), the stale daemon would fail to fork child processes with
MODULE_NOT_FOUNDerrors because those paths no longer existed.Studio’s quit handler calls
site stop --all, but if no sites are actively running at quit time, the command returns early without killing the PM2 daemon. The daemon would then linger with outdated module paths baked in, breaking subsequent launches from other workspaces.Proposed Changes
killDaemonAndChildrenAndExitProcess()whensite stop --allis invoked, even if no sites are runningTesting Instructions
npx pm2 listshould show an empty tablePre-merge Checklist