bndtools / bnd

Bnd/Bndtools. Tooling to build OSGi bundles including Eclipse, Maven, and Gradle plugins.
https://bndtools.org
Other
526 stars 304 forks source link

EphemeralPortTest failing intermittently #6122

Closed reckart closed 1 month ago

reckart commented 1 month ago

When I run ./gradlew :build, the following test sometimes fails

EphemeralPortTest > automatic_supplier() FAILED
    java.net.BindException: Address already in use
        at java.base/sun.nio.ch.Net.bind0(Native Method)
        at java.base/sun.nio.ch.Net.bind(Net.java:555)
        at java.base/sun.nio.ch.Net.bind(Net.java:544)
        at java.base/sun.nio.ch.NioSocketImpl.bind(NioSocketImpl.java:643)
        at java.base/java.net.ServerSocket.bind(ServerSocket.java:393)
        at java.base/java.net.ServerSocket.<init>(ServerSocket.java:279)
        at java.base/java.net.ServerSocket.<init>(ServerSocket.java:172)
        at aQute.bnd.test.net.EphemeralPortTest.automatic_supplier(EphemeralPortTest.java:17)

1 test completed, 1 failed

I don't really see how it can fail because what it does is check if a port is free and then allocate the port again. So my guess is that when the port is allocated and then released, maybe the OS does not immediately release it (race condition).

Has anybody also seen this?

macOS 14.4.1 openjdk version "17.0.3" 2022-04-19 LTS

reckart commented 1 month ago

Apparently same problem in another test:

> Task :biz.aQute.bndlib.comm.tests:test

HttpClientProxyTest > testSecureSocksAuthenticatingWithGoodUserSecure() FAILED
    java.io.IOException: Failed to start Socks Proxy Server on port 49171
        at aQute.bnd.comm.tests.HttpClientProxyTest.createSecureSocks5(HttpClientProxyTest.java:454)
        at aQute.bnd.comm.tests.HttpClientProxyTest.testSecureSocksAuthenticatingWithGoodUserSecure(HttpClientProxyTest.java:211)

        Caused by:
        java.net.BindException: Address already in use
            at java.base/sun.nio.ch.Net.bind0(Native Method)
            at java.base/sun.nio.ch.Net.bind(Net.java:555)
            at java.base/sun.nio.ch.Net.bind(Net.java:544)
            at java.base/sun.nio.ch.NioSocketImpl.bind(NioSocketImpl.java:643)
            at java.base/java.net.ServerSocket.bind(ServerSocket.java:393)
            at java.base/java.net.ServerSocket.<init>(ServerSocket.java:279)
            at sockslib.server.BasicSocksProxyServer.createServerSocket(BasicSocksProxyServer.java:235)
            at sockslib.server.BasicSocksProxyServer.start(BasicSocksProxyServer.java:227)
            at aQute.bnd.comm.tests.HttpClientProxyTest.createSecureSocks5(HttpClientProxyTest.java:451)
            ... 1 more
chrisrueger commented 1 month ago

@reckart Can you try a clean build (./gradlew clean build)

I also had failing testcases when just using ./gradlew build , but adding clean helped for me. Tested two times in a row with success.

Btw: In my case different tests failed. e.g. It my case P2IndexerTest was failing often.

pkriens commented 1 month ago

I remember this problem from years ago on Windows. The EphemeralPort class was introduced to solve this issue :-( However, can't recall when I last saw this. Did you recently upgrade MacOS? I am on 12.7 still.

We could change this port allocator to not use ephemeral ports but allocation from a range and go through it cyclically. This would not reuse previous numbers for a long time.

Then again, when I look on my machine, it seems to allocate the ephemeral ports in exactly that way.

Quite puzzled about this. We could add a delay in the EphemeralPort?

reckart commented 1 month ago

Well I was using macOS 14.4.1 when I ran into this and today upgraded to 14.5 - let's see...

reckart commented 1 month ago

@chrisrueger I tried clean build, but I still run into failures (see https://github.com/bndtools/bnd/issues/6123):

ProjectResolverTest > testAugment() FAILED
    org.opentest4j.AssertionFailedError: expected: <true> but was: <false>
        at app//org.junit.jupiter.api.AssertionFailureBuilder.build(AssertionFailureBuilder.java:151)
        at app//org.junit.jupiter.api.AssertionFailureBuilder.buildAndThrow(AssertionFailureBuilder.java:132)
        at app//org.junit.jupiter.api.AssertTrue.failNotTrue(AssertTrue.java:63)
        at app//org.junit.jupiter.api.AssertTrue.assertTrue(AssertTrue.java:36)
        at app//org.junit.jupiter.api.AssertTrue.assertTrue(AssertTrue.java:31)
        at app//org.junit.jupiter.api.Assertions.assertTrue(Assertions.java:180)
        at app//biz.aQute.resolve.ProjectResolverTest.testAugment(ProjectResolverTest.java:116)
chrisrueger commented 1 month ago

@reckart Did by any chance https://github.com/bndtools/bnd/issues/6123#issuecomment-2126499751 fix this issue too? (the settings.xml stuff)?

reckart commented 1 month ago

Interestingly yes - although, I have no idea how those two issues would connect to each other.

chrisrueger commented 1 month ago

Interestingly yes - although, I have no idea how those two issues would connect to each other.

@reckart Only guessing:

The methods like

are doing something with ConnectionSettings

image

Since you previously had a settings.xml which might have been picked up... Maybe something is leaking from previous tests which block the port (because of some settings in settings.xml).

If you put back your settings.xml and the test fails again, this would make a strong case for it.

If you find the time you could verify this with the improved logging in https://github.com/bndtools/bnd/pull/6130