Skip to content

Studio: Check if port is open before starting servers - #1236

Merged
gavande1 merged 4 commits into
trunkfrom
stu-103-studio-starting-a-site-with-already-busy-port
Apr 22, 2025
Merged

Studio: Check if port is open before starting servers#1236
gavande1 merged 4 commits into
trunkfrom
stu-103-studio-starting-a-site-with-already-busy-port

Conversation

@gavande1

@gavande1 gavande1 commented Apr 22, 2025

Copy link
Copy Markdown
Contributor

Related issues

Proposed Changes

  • Added port availability checking before starting servers
  • Improved error handling for busy ports

Testing Instructions

  • Check out this branch and run npm start
  • Start the server for your site and confirm that the server starts normally.
  • Note the port number. e.g. 8881 and stop the server.
  • Open a new terminal and run php -S localhost:{PORT_NUMBER}. e.g. php -S localhost:8881
  • Come back to the studio and try to start the server. It should show the following alert:

CleanShot 2025-04-22 at 10 24 46@2x

  • Confirm that the site running status returns to normal and shows the Start button.
  • Go back to the terminal where you started php -S localhost:8881, press cmd + c to terminate the server. This would free up port 8881.
  • Come back to the studio and start the server.
  • Confirm the site server started without any problem, and you can browse your test site.

Bonus Test

  • Open your appdata-v1.json (cat "~/Library/Application Support/Studio/appdata-v1.json")
  • Look at the sites key, note down the highest occupied port number. For example, in my case it's 8883.
  • Add 1 to that port number. So becomes 8884
  • Open a new terminal session and run php -S localhost:8884
  • Come back to the studio and add a new site.
  • Check the port number for the new site; it should be 8885. When creating the site, port 8884 was busy, so Studio skipped it and chose the next available port. If 8885 is also busy, the port finder will increment by 1 to find the next available port.

Pre-merge Checklist

  • Have you checked for TypeScript, React or other console errors?
Comment thread src/lib/port-finder.ts
return new Promise( ( resolve ) => {
const server = http.createServer();
// First try to connect to the port
const socket = new net.Socket();

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The previous isPortFree() implementation used http.createServer().listen() to check port availability. However, this was leading to false positives. The port was showing free when it was actually in use. This might be happening because listen() may not immediately fail if the port is in a TIME_WAIT state or due to OS-level race conditions.

The updated logic first attempts to connect to the port using a socket to improve reliability. A successful connection confirms the port is in use. If the connection fails, we try to bind to the port to to make sure it's truly available.

@gavande1
gavande1 marked this pull request as ready for review April 22, 2025 05:27
@gavande1
gavande1 requested review from a team and youknowriad April 22, 2025 05:29

@epeicher epeicher left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have tested it, and it works as advertised. I love this change as it improves the UX when there are some errors, and those errors of port in use are very common so this is 💯 . I have left a non-blocking comment about the style of a method but overall this LGTM!

Port in use for existing site Having the next port in use for new site
CleanShot 2025-04-22 at 09 18 40@2x CleanShot 2025-04-22 at 09 25 45@2x
Comment thread src/lib/port-finder.ts Outdated
Comment thread src/hooks/use-site-details.tsx Outdated
getIpcApi().showErrorMessageBox( {
title: __( 'Failed to start the site server' ),
message: __(
`The site server failed to start because the port is already in use. Please close any local development apps that may be using port ${ port } and try again.`

@katinthehatsite katinthehatsite Apr 22, 2025

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One idea that comes to mind as a potential improvement even further could be that instead of the Ok button as shown now, we could add a button that says something like Try another port and it could automatically attempt to start the server on a different port.

@gcsecsey gcsecsey Apr 22, 2025

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This pattern is also used by some build tools, without prompting the user. Eg. when using Vite, if the default port is occupied, it just increments the dev port until it finds a free port.
image

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds good 👍

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the suggestion, @katinthehatsite. This was one of the suggestions in the linked issue. However, it would require a larger effort than the current PR. I believe this PR improves the experience significantly.

@katinthehatsite

Copy link
Copy Markdown
Contributor

The testing steps worked for me and the implementation works as expected 👍 I added one suggestion that we can consider to potentially improve the user experience further.

@gcsecsey gcsecsey left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This works well for me too.

image
@gavande1
gavande1 merged commit e720f78 into trunk Apr 22, 2025
@gavande1
gavande1 deleted the stu-103-studio-starting-a-site-with-already-busy-port branch April 22, 2025 14:12
bcotrim pushed a commit that referenced this pull request Apr 22, 2025
* Update a way to check if port is open

* Check if port is open before starting servers

* Do not show open logs button

* Accept port as args in #isPortFree
bgrgicak pushed a commit that referenced this pull request Apr 23, 2025
* Update a way to check if port is open

* Check if port is open before starting servers

* Do not show open logs button

* Accept port as args in #isPortFree
@fredrikekelund

Copy link
Copy Markdown
Contributor

We also have checkPortInWindows in src/lib/proxy-server.ts. There's an obvious difference in that the checkPortInWindows function only runs on Windows, but I still wonder if we shouldn't refactor that function and PortFinder::isPortFree to share the same underlying logic. WDYT, @gavande1?

@gavande1

gavande1 commented Apr 24, 2025

Copy link
Copy Markdown
Contributor Author

Thanks @fredrikekelund for bringing it to my attention. I don't see any reason not to refactor src/lib/proxy-server.ts to share similar logic. I will create a follow-up PR for that.

@gavande1

Copy link
Copy Markdown
Contributor Author

For posterity, I have created a PR #1281 to address the above suggestion.

@gavande1 gavande1 self-assigned this May 8, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

6 participants