Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Leaking file descriptor / socket within DomainSocket tooling #32423

Closed
knalli opened this issue Sep 19, 2022 · 4 comments
Closed

Leaking file descriptor / socket within DomainSocket tooling #32423

knalli opened this issue Sep 19, 2022 · 4 comments
Assignees
Labels
type: bug A general bug
Milestone

Comments

@knalli
Copy link

knalli commented Sep 19, 2022

This is the result of a long journey searching for a very strange leaking issue. I hope I have put everything together again, found the right address. Otherwise please ask for more details.

So, let's start of my finding: Probably this affects the component "buildpack" (unsure how you named this), but not the actual "main" framework/boot library system.

As far as I can say, I would say that the call chain of

# org.springframework.boot.buildpack.platform.socket
DomainSocket.get(String path)
-> LinuxDomainSocket(String path)
-> DomainSocket(String path)
-> #open(String path)

results into a resource leak under the condition the path does not exist. I can see there is native code involved, because the exception happens in the connect method:

Caused by: com.sun.jna.LastErrorException: [2] No such file or directory
 at com.github.dockerjava.transport.LinuxDomainSocket.connect(Native Method)
 at com.github.dockerjava.transport.LinuxDomainSocket.connect(LinuxDomainSocket.java:49)
 at com.github.dockerjava.transport.DomainSocket.open(DomainSocket.java:69)
 at com.github.dockerjava.transport.DomainSocket.<init>(DomainSocket.java:59)

Yes, the package differs but it is only shaded (as far as I can say it is identical).

I have a demo provided at this repository.

// socket exist
BEGIN = Current open files: 70
Creating socket...
INIT = Current open files: 73
Closing socket..
EXIT = Current open files: 72

// socket does not exist
BEGIN = Current open files: 70
Creating socket...
Error: com.sun.jna.LastErrorException: [2] No such file or directory
INIT = Current open files: 73
No open socket
EXIT = Current open files: 73

Please have a look at the open files counter (which is based on the same as FileDescriptorMetrics).


I have found this class while searching for a leak when using the library docker-java which have included these classes (credits of Phil Webb left, so I found the origin here). Because you (the project) are the actual author, I guess this issue is better addresses here. If the finding is correct and/or we find a solution, I will follow-up for the required changes to them.


The symptom is the system (linux) reports for the java process with lsof -p <pid> | grep STREAM multiple entries

java    1 user  240u     unix 0xffff9b1e9739f080       0t0 4063746316 type=STREAM

A couple of them are fine, but this list grows only in one of our applications. I took some time isolating the actual culprit, at the end speaking for this context the application does (reduced): call each minute DomainSocket.get("/var/lib/docker.sock"), but this socket does not exist on this system. (For sake of simplicity I have reduced the dynamic aspect here.)

On every "call", the list grows for more entries (which means more open files). The counter "open files" in the java runtime grows as well. The (linux) system reports this files as sockets without any meta information except the mapped pid.


I am not sure whether the file descriptor should stay (I would say no, because the exception is thrown) or the call must be guarded with "file exist" check. However, I guess this should be part of at least the DomainSocket class?

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged label Sep 19, 2022
@scottfrederick
Copy link
Contributor

Thanks for getting in touch.

the library docker-java which have included these classes

Are you referring to the project at https://github.com/docker-java/docker-java or another project? I see no indication that this docker-java library is using any code from Spring Boot. Can you point us to the code in the project that is using this class from Spring Boot?

A couple of them are fine, but this list grows only in one of our applications.

The code in the org.springframework.boot.buildpack package is intended to be used by the Cloud Native Buildpacks integration in the Spring Boot Maven and Gradle plugins. It is in a separate module, with some public classes, so that it can be shared between these plugin modules. It is not intended to be used as a general-purpose Docker integration library. Can you share more information about how you are using this code from Spring Boot?

@scottfrederick scottfrederick added the status: waiting-for-feedback We need additional information before we can continue label Sep 19, 2022
@knalli
Copy link
Author

knalli commented Sep 19, 2022

Ok, that was maybe a bit confusing. It seems they simply "copied" your code. I thought it would be better reaching you at first because your are the original author and would be affected also. The copy is e.g. here https://github.com/docker-java/docker-java/blob/dd1735831f12f787070b667d33ac1c4103630c95/docker-java-transport/src/main/java/com/github/dockerjava/transport/DomainSocket.java

They (and me) dont use your specific code directly. If you think you are not affected for this or it is not relevant, we can close this.

Don't get me wrong, I just thought you were interested in this one. :)

@spring-projects-issues spring-projects-issues added status: feedback-provided Feedback has been provided and removed status: waiting-for-feedback We need additional information before we can continue labels Sep 19, 2022
@scottfrederick
Copy link
Contributor

scottfrederick commented Sep 19, 2022

Thank you for clarifying the copying of code vs direct use, that makes sense now.

Spring Boot users shouldn't be affected since the code is only called by the Maven and Gradle plugins, and runs in the context of a Maven goal or Gradle task. It will not make its way into a user's application unless they choose to use it directly, which is unlikely since the class has little value on its own and the code in Spring Boot that calls it is package-private.

Thanks again for the high-quality issue with the demo project, but this should be reported to the docker-java team so they can look into it in the context of their use cases.

@scottfrederick scottfrederick closed this as not planned Won't fix, can't repro, duplicate, stale Sep 19, 2022
@scottfrederick scottfrederick added status: invalid An issue that we don't feel is valid and removed status: waiting-for-triage An issue we've not yet triaged status: feedback-provided Feedback has been provided labels Sep 19, 2022
@scottfrederick
Copy link
Contributor

After some discussion, we've decided this is worth looking into for the Boot plugins. Though it won't affect user applications, there is a chance that the Gradle or Maven daemon processes could be long-running and encounter this condition.

@scottfrederick scottfrederick added type: bug A general bug and removed status: invalid An issue that we don't feel is valid labels Sep 20, 2022
@scottfrederick scottfrederick added this to the 2.6.x milestone Sep 20, 2022
@wilkinsona wilkinsona changed the title Leaking file descriptor / socket within DomainSocket tooling? Leaking file descriptor / socket within DomainSocket tooling Sep 21, 2022
@wilkinsona wilkinsona modified the milestones: 2.6.x, 2.7.x Nov 24, 2022
@mhalbritter mhalbritter self-assigned this Sep 19, 2023
@mhalbritter mhalbritter modified the milestones: 2.7.x, 2.7.16 Sep 19, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: bug A general bug
Projects
None yet
Development

No branches or pull requests

5 participants