Yogesh Deore
Yogesh Deore

Reputation: 1

Is there any way to solve "java.lang.RuntimeException: Unable to find a free port" issue

I am using Jenkins, Maven, and Chromedriver to execute selenium scripts but while running multiple projects at same time it is giving me this error. How can we solve this issue? I have scheduled multiple scripts on jenkins and which are executed when code is pushed to git.

java.lang.RuntimeException: Unable to find a free port at org.openqa.selenium.net.PortProber.findFreePort(PortProber.java:67) at org.openqa.selenium.remote.service.DriverService$Builder.build(DriverService.java:351) at org.openqa.selenium.chrome.ChromeDriverService.createDefaultService(ChromeDriverService.java:94) at org.openqa.selenium.chrome.ChromeDriver.(ChromeDriver.java:157) at Check.Status.Tests.driverSetup(Tests.java:33)

Upvotes: 0

Views: 2221

Answers (2)

zooppoop
zooppoop

Reputation: 171

For anyone that runs into this. The linux system I was running on had the /proc/sys/net/ipv4/ip_local_port_range set to 1024 - 65535 Causing the Selenium code to always choose 1024. I was misunderstanding that it's goal was to choose a port in between these ports. But it is looking for a port outside of this range as to not conflict with other applications that need say lots of ports or short term use. So basically selenium restricts it self to 1024 - 1024 or if you changed it to 1025 - 65535 it would allow it to use two ports.

This system was specifically set to allow to use the full range as it was setup to be a call server where it handles a large number of calls and needs a large range to work with.

So simply change this range to be something where you give enough ports on either side of the range.

Linux limits ports < 1024 to Root access only. Selenium's code I believe also will not try to use those ports. so you need to offer it something > 1024 to something or open up something on the high end so < 65535.

so change your /proc/sys/net/ipv4/ip_local_port_range say something like echo "32387 65535" > /proc/sys/net/ipv4/ip_local_port_range or echo "1024 50000" > /proc/sys/net/ipv4/ip_local_port_range

This above is only temporary. Most linux systems will have a sysctl.conf file where you can make these changes in.

Upvotes: 0

undetected Selenium
undetected Selenium

Reputation: 193088

This error message...

java.lang.RuntimeException: Unable to find a free port

...is a RuntimeException which is the superclass of those exceptions that can be thrown during the normal operation of the Java Virtual Machine.


Protecting the ports that chromedriver use

There is nothing much we can do about the port usage as @barancev mentions ChromeDriver attempts to find a free Ephemeral port using a system-dependent ephemeral port range detector. An ephemeral port is a short-lived endpoint that is created by the operating system when a program requests any available user port. The operating system selects the port number from a predefined range, typically between 1024 and 65535, and releases the port after the related TCP connection terminates.

By default, the system can create a maximum of approximately 4,000 ephemeral ports that run concurrently on Windows Server 2003 and approximately 16,000 on Windows Server 2008.

You can find a detailed discussion in How do I protect the ports that chromedriver use?


Issue in details

  • As per @visionscaper's comment on Windows systems you need to remove / comment out the following type of entries from C:\Windows\System32\Drivers\etc\hosts file:

    127.0.0.1 my-site.local
    192.168.100.48 localhost
    
  • As per @DavidGDD's comment on Linux systems in PortProber.java and LinuxEphemeralPortRangeDetector.java there is a case in createAcceptablePort in which is always returning the same port, not random.

    • When you have defined in the /proc/sys/net/ipv4/ip_local_port_range the port range as 1024-65535, the method always returns 1024.
    • When you change your range defined in the file to 1025-65535 (or any other range) it will work returning random ports.
  • @tflori mentions from Selenium point of view:
    • LinuxEphemeralPortRangeDetector.java had more than one space between the two ports. So the result was [1025, , , , 65535] then Integer.parseInt(split[1]); throws and the default is used which leads to the same issue we had without modifying the lower port.
    • PortProber.java we were geting the highest and lowest ports from the platform and then we overwrite one or the other 1024 or 65535.

Solution

This merge solves the port negotiation problem on linux and other platforms. The removed code leads to the result that FIRST_PORT and LAST_PORT is both set to 1024 which always returns 1024. In fact we should trust the ephemeral ports reports by the detector. With the min and max we just assure a valid port range. So you need to ensure that:

  • JDK is upgraded to current levels JDK 8u222.
  • Selenium is upgraded to current levels Version 3.141.59.
  • ChromeDriver is updated to current ChromeDriver v77.0 level.
  • Chrome is updated to current Chrome Version 77.0 level. (as per ChromeDriver v77.0 release notes)
  • Clean your Project Workspace through your IDE and Rebuild your project with required dependencies only.
  • If your base Web Client version is too old, then uninstall it and install a recent GA and released version of Web Client.
  • Take a System Reboot.
  • Execute your @Test as non-root user.
  • Always invoke driver.quit() within tearDown(){} method to close & destroy the WebDriver and Web Client instances gracefully.

Upvotes: 1

Related Questions