[CONJ-1007] Socket file descriptors are leaked after connecting with unix socket if DB is not up running Created: 2022-09-01  Updated: 2022-09-15  Resolved: 2022-09-02

Status: Closed
Project: MariaDB Connector/J
Component/s: Other
Affects Version/s: None
Fix Version/s: 2.7.7, 3.0.8

Type: Bug Priority: Major
Reporter: Guopeng Liang Assignee: Diego Dupin
Resolution: Fixed Votes: 0
Labels: None

Issue Links:
Relates
relates to CONJ-382 Leaked Sockets when server reach maxi... Closed
relates to CONJ-513 Connector/J Leaking socket file descr... Closed

 Description   

If the connector is configured using unix socket, and attempts to connect when the DB is not up (the path to unix socket does not exist or not able to connect), it fails as expected. However after that, a socket file descriptor is not closed and leaked.

How to reproduce:

Add a unit test like this:

@Test
public void testConnectWithUnixSocketWhenDBNotUp () {
 
    String url = "jdbc:mariadb://localhost:3306";
    Properties properties = new Properties();
    properties.setProperty("localSocket", "/tmp/not_valid_socket");
    properties.setProperty("localSocketAddress", "localhost");
 
    java.sql.Driver driver = new org.mariadb.jdbc.Driver();
 
    System.out.println ("Make a break point here and check netstat/lsof");
 
    for (int i = 0; i < 10; i++) {
        assertThrows(SQLNonTransientConnectionException.class, () -> {
            driver.connect(url, properties);
        });
    }
 
    System.out.println("Make a break point here and check again");
}

Run the unit test in a Linux env, and set break points as shown.
Use below commands to compare at the point of before and after making connections, and verify that the socket file descriptors are leaked.

Below example shows the "after" condition only:

#Find the process ID and replace here
> export pid=32532

> netstat -apnx | grep $pid
unix 2 [ ] STREAM CONNECTED 39256846 7767/java
unix 2 [ ] STREAM 39256869 7767/java
unix 2 [ ] STREAM 39256885 7767/java
unix 2 [ ] STREAM 39256871 7767/java
unix 2 [ ] STREAM 39256883 7767/java
unix 2 [ ] STREAM CONNECTED 39256860 7767/java
unix 2 [ ] STREAM 39256866 7767/java
unix 2 [ ] STREAM 39256873 7767/java
unix 2 [ ] STREAM 39256879 7767/java
unix 2 [ ] STREAM 39256877 7767/java
unix 2 [ ] STREAM 39256881 7767/java
unix 2 [ ] STREAM 39256875 7767/java

> lsof -p $pid | grep socket | wc -l
13



 Comments   
Comment by Diego Dupin [ 2022-09-02 ]

nice detailed description !
corrected with https://github.com/mariadb-corporation/mariadb-connector-j/commit/f631c4e269720e674fcecdbaa6e82764e4b4a1d3
(socket is always closed by when establishing connection for windows pipe or unix socket)

Comment by Guopeng Liang [ 2022-09-02 ]

Thank you Diego!

I was about to submit a pull request though.

I was about to fix that in UnixDomainSocket, which is more specific. Your fix seems to be in the code path which applies to TCP as well? I don't see any issue currently when using TCP connection which leaks and the issue is specific to Unix socket. Generally I also think we should not expect a resource needs to be closed explicitly, if it fails to create or connect.

Another concern is that, for some reason we want to stick with version 1.x or 2.x. Your fix applies to ConnectionHelper which does not exist in older versions. Fixing in UnixDomainSocket is more specific and can apply to all versions in the same way.

What is your opinion?

Comment by Guopeng Liang [ 2022-09-02 ]

It might not be the same cause of CONJ-513, as that issue seems to be related to hibernate-hikaricp.

Comment by Guopeng Liang [ 2022-09-02 ]

I also found that this issue SEEMS to be fixed in latest 1.x by this commit: https://github.com/mariadb-corporation/mariadb-connector-j/commit/a8f8ab9acb80876c65303eb55950a6ab16de3c16, with this code snip:

        catch (IOException ioException) {
            ensureClosingSocketOnException();
            throw ioException;
        } 

The code has been changed a lot towards 2.x and 3.x so this logic seems not preserved in 2.x and 3.x.

However I remember I still had the leaking issue when using latest 1.x version in the application. I need to retest it again to confirm.

Comment by Diego Dupin [ 2022-09-05 ]

1.x just become non supported. (java 7 EOL + 5 years support)
about correction, you're right about closing directly on UnixDomainSocket.connect(), improved. (https://github.com/mariadb-corporation/mariadb-connector-j/blob/develop/src/main/java/org/mariadb/jdbc/client/socket/impl/UnixDomainSocket.java#L159)

Comment by Guopeng Liang [ 2022-09-06 ]

Thank you again. I see you also made similar fix to 2.x version as well which is perfect for us.

When are you planning on releasing it?

Comment by Diego Dupin [ 2022-09-07 ]

This is the only issue for 2.7.7 for now. Release date for 2.7.7 is programmed to the 1st December.
(The release date may be earlier in the case of a customer issue / a critical issue)

Comment by Guopeng Liang [ 2022-09-15 ]

CONJ-382 also fixes the same issue as CONJ-1007, however CONJ-382 is only present in 1.x.

Comment by Diego Dupin [ 2022-09-15 ]

CONJ-1007 only concerns connect when the DB is not up, other cases where leaks on connection occurs where already corrected by CONJ-382.
Issue is not ported on 1.x because not supported anymore.

Generated at Thu Feb 08 03:19:55 UTC 2024 using Jira 8.20.16#820016-sha1:9d11dbea5f4be3d4cc21f03a88dd11d8c8687422.