Copilot commented on code in PR #2645:
URL: https://github.com/apache/plc4x/pull/2645#discussion_r3585086341


##########
plc4j/transports/tcp/src/test/java/org/apache/plc4x/java/transport/tcp/TcpTransportInstanceTest.java:
##########
@@ -290,6 +290,50 @@ void testConcurrentReadWrite() throws Exception {
         assertTrue(doneLatch.await(10, TimeUnit.SECONDS));
     }*/
 
+    @Test
+    void testConstructor_failedBind_doesNotLeakFileDescriptors() throws 
Exception {
+        // getOpenFileDescriptorCount() is only exposed on Unix-flavoured JVMs
+        com.sun.management.UnixOperatingSystemMXBean osBean;
+        try {
+            osBean = (com.sun.management.UnixOperatingSystemMXBean)
+                
java.lang.management.ManagementFactory.getOperatingSystemMXBean();
+        } catch (ClassCastException e) {
+            org.junit.jupiter.api.Assumptions.assumeTrue(false,
+                "Open file descriptor count not available on this platform");
+            return;
+        }
+
+        // Occupy a specific local port so binding our own channel to it 
deterministically fails
+        // with BindException
+        try (ServerSocketChannel occupier = ServerSocketChannel.open()) {
+            occupier.bind(new InetSocketAddress("127.0.0.1", 0));
+            int occupiedPort = ((InetSocketAddress) 
occupier.getLocalAddress()).getPort();
+
+            TcpTransportConfiguration config = new TcpTransportConfiguration();
+            config.receiveBufferSize = 81920;
+            config.localAddress = "127.0.0.1";
+            config.localPort = occupiedPort;
+            // Never actually reached - bind() fails first - but must be a 
well-formed address.
+            InetSocketAddress remoteAddress = new 
InetSocketAddress("127.0.0.1", occupiedPort);
+
+            int attempts = 20;
+            long before = osBean.getOpenFileDescriptorCount();
+            for (int i = 0; i < attempts; i++) {
+                assertThrows(TransportException.class, () ->
+                    new TcpTransportInstance(remoteAddress, config, 
AuditLog.builder().build())
+                );
+            }
+            long grown = osBean.getOpenFileDescriptorCount() - before;
+
+            // Without the fix each failed constructor call leaks the 
SocketChannel it opened
+            // before bind() failed, so fd count grows by ~1 per attempt. With 
the fix it stays flat.
+            assertTrue(grown < attempts,
+                "Open file descriptor count grew by " + grown + " across " + 
attempts
+                    + " failed bind attempts - each failed 
TcpTransportInstance constructor call "
+                    + "is leaking its SocketChannel instead of closing it");

Review Comment:
   The assertion is too weak for the stated intent (“fd count stays flat”): 
`grown < attempts` would still pass even if the constructor leaked file 
descriptors intermittently or on only some iterations (e.g., `grown == attempts 
- 1`). Tighten this to assert no per-attempt growth (optionally with a small 
tolerance for background noise).



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to