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

Gradle - Too many open files #26115

Open
Rodrigolmti opened this issue Aug 15, 2023 · 33 comments
Open

Gradle - Too many open files #26115

Rodrigolmti opened this issue Aug 15, 2023 · 33 comments
Labels
a:bug has:reproducer Indicates the issue has a confirmed reproducer has:workaround Indicates that the issue has a workaround in:daemon in:wrapper

Comments

@Rodrigolmti
Copy link

Current Behavior

Recently I'm getting a lot of errors on my project, and we do not have any clue what may be causing this. Each time we have a different error, but we can summarize it as (Too many open files).

Closing the Android Studio and killing all java instances solves the problem, but after 2/3 Gradle syncs the problem comes back.

`Caused by: org.gradle.api.resources.MissingResourceException: Could not read build file '/Users/rodrigo.martins/Code/skipthedishes_android_v3/features/order/review/api/build.gradle.kts' as it does not exist.

Caused by: java.lang.NullPointerException: Cannot read the array length because "sessionFiles" is null
`

gradle_error.txt
gradle_sync.txt

I have attached some supporting files that contain more details about the error, stack trace and dumps.

Expected Behavior

I can sync the project without getting error or having to increase the number of open files that my system suppports.

Context (optional)

Too many open files

The issue arises consistently every time we attempt to run a Gradle sync. Neither invalidating the cache nor performing a clean build has resolved the issue. This problem is not confined to a specific type of machine; it occurs on M1, M2, and Intel-based machines alike.

The error message lacks detailed information, but we have attached logs and stack traces to this issue. This issue has persisted across various Android Studio versions over a period of time.

Tested solution:

Add -XX:-MaxFDLimit to studio.vmoptions.
Reference: gradle/gradle#17274
Run the attached script update_max_limit.sh which is supposed to increase the limit of open files. Initially, it helped, but the PC started to slow down, and now the script is no longer effective.
The script is based on this blog post.
Sometimes it helps to run pkill -f "java|studio", but now this command is also not working anymore.
We also have an open issue on the Gradle forum, but there have been no answers so far.
Forum link: discuss.gradle.org/t/caused-by-java-io-ioexception-error-24-too-many-open-files/45884
This issue seems to have started after we added Compose to the project and Gradle conventional plugins. We are not sure which one is the root cause or if this is the cause at all.

I have attached a sample of our project with reduced files, along with logging files of the problem and the IDA as requested.

stracktrace.txt
threadDump-20230814-110815.txt
project.zip
idea.log
local_history.txt
open_files.txt

Steps to Reproduce

This is a project that is supposed to simulate the issue: github.com/napstr/gradle-darwin-maxfdlimit. We also tried to make the changes proposed in this repository, but the issue still occurs.

Gradle version

7.4.2 / 7.5

Build scan URL (optional)

https://scans.gradle.com/s/uieftr67or3qw

Your Environment (optional)

Studio Build:

Android Studio Giraffe | 2022.3.1 Build #AI-223.8836.35.2231.10406996, built on June 29, 2023 Runtime version: 17.0.6+0-17.0.6b829.9-10027231 aarch64 VM: OpenJDK 64-Bit Server VM by JetBrains s.r.o. macOS 13.5 GC: G1 Young Generation, G1 Old Generation Memory: 4096M Cores: 8 Metal Rendering is ON

Version of Gradle Plugin: 7.4.2 Version of Gradle: gradle-7.4.2-bin Version of Java: openjdk 17.0.7 2023-04-18 OS: Mac OS Ventura 13.5

@jbartok
Copy link
Member

jbartok commented Aug 22, 2023

Thank you for your interest in Gradle!

We are trying to figure out if this is an AGP issue or a problem in the Build Tool. We will keep you posted.

@jbartok jbartok added 👋 team-triage Issues that need to be triaged by a specific team to-triage and removed to-triage need-help-triaging labels Aug 22, 2023
@Rodrigolmti
Copy link
Author

Hello, any update on this?

@github-actions github-actions bot removed the to-triage label Sep 6, 2023
@ov7a
Copy link
Member

ov7a commented Sep 12, 2023

Thank you for providing a valid report.

The issue is in the backlog of the relevant team, but the existence of a workaround makes it non-critical, so it might take a while before a fix is made.


Gradle should always pass -XX:-MaxFDLimit in the wrapper script.

See also this gist.

The workaround is to add -XX:-MaxFDLimit to the wrapper scripts.
The fix would be adding it to all generated scripts.

@ov7a ov7a added in:wrapper has:reproducer Indicates the issue has a confirmed reproducer has:workaround Indicates that the issue has a workaround and removed 👋 team-triage Issues that need to be triaged by a specific team labels Sep 12, 2023
@Rodrigolmti
Copy link
Author

Rodrigolmti commented Sep 13, 2023

I see, thank you for the update.

Can you provide an example on how can I add the -XX: -MaxFDLimit into the wrapper script? We tried the following approach https://github.com/schnapster/gradle-darwin-maxfdlimit/blob/master/patched_gradlew, however, our team with 16 developers is facing this problem every day, after 3 Gradle syncs or builds, even with the updated wrapper script.

And the only way to fix is by running pkill -f "java|studio" on a terminal and starting the AS again, however, the issue happens again. So we are stuck on a loop that is impacting the whole team, for some time already.

So, i do appreciate any help with this.

@ov7a
Copy link
Member

ov7a commented Sep 13, 2023

@Rodrigolmti Have you tried setting environment variables $JAVA_OPTS or $GRADLE_OPTS without modifying wrapper script?

@Rodrigolmti
Copy link
Author

Well, for a moment this seemed to fix the problem, however after some time it came back again.

I've added:

export JAVA_OPTS="-XX:-MaxFDLimit" export GRADLE_OPTS="-XX:-MaxFDLimit"

To my bash file.

@Rodrigolmti
Copy link
Author

We managed to update the project to Gradle 8.3 and Kotlin 1.9.10, the problem happens less than what was happening on Gradle 7.4, however it is still there. I would appreciate it if you can remove the tag has workaround, since it does not have, or at least not these that you recommended.

Thank you.

@ov7a ov7a removed the has:workaround Indicates that the issue has a workaround label Sep 19, 2023
@eskatos
Copy link
Member

eskatos commented Sep 19, 2023

We can't reproduce the problem with this repository https://github.com/schnapster/gradle-darwin-maxfdlimit

If you still see something piling up file descriptors, there might be a leak somewhere.
We have extensive tests for the Gradle daemon itself. It could come from something in your build logic.

You can use fileleak-detector to track it down.
See https://discuss.gradle.org/t/tracking-down-unreleased-file-handles/23571/3

I still consider this issue being about the wrapper scripts that should always set MaxFDLimit and has a workaround.
If you find a leak in the Gradle daemon we can think of opening a different issue.

@eskatos eskatos added the has:workaround Indicates that the issue has a workaround label Sep 19, 2023
@joshfriend
Copy link

The issue should be easily replicated with this repo.

@eskatos
Copy link
Member

eskatos commented Sep 20, 2023

Looking at file-leak-detector logs with this large repo we can see that the Groovy DSL is opening quite a number of file descriptors while compiling and evaluating build scripts. With 5k projects this makes a lot of file descriptors and trips up the limits.

Changing the system configuration to raise the maximum limit is out of Gradle's scope. However, the wrapper scripts try to raise the user limit for the Gradle process on all platforms except cygwin and macos. In the same fashion, we could change the wrapper scripts to try to do that too on macos by running ulimit -n unlimited.

@ov7a ov7a removed the to-triage label Sep 20, 2023
@Rodrigolmti
Copy link
Author

Ok, so we did try to use ulimit -n unlimited and ulimit -f unlimited, but according to this different issue that have I opened for Android Studio https://issuetracker.google.com/issues/295792460, apple may have added some restrictions for changing the max open file config on the latest macOS versions. So, it may be the cause that the workaround worked in the past, but it is not working anymore due to these restrictions.

As described on the issue, we already tested a bunch of different solutions that we found thought the internet. None has worked so far.

We have 16 engineers facing this problem basically every day after 3 Gradle syncs or project build. We are going to take a look at the fileleak-detector, and check if we can collect any data that may help you help us.

Furthermore, we are at the place where, if we decide to remove the build-logic module where we keep all our convention plugins, it will require a considerable amount of work and time. So I want to explore all the cases before, specially because it is generating some benefits for us today, due to modularization.

We tried Gradle enterprise before but seems that we do not meet the minimum criteria and Gradle enterprise do not offer this type of solution or help. In case that any of you have a few minutes where we can show to you what is happening, maybe we can discover something more relevant.

Thank you for the help.

@eskatos
Copy link
Member

eskatos commented Sep 20, 2023

Thank you for the context and the link to the Android issue.

https://developer.apple.com/forums//thread/735798

This looks like a bug in recent macos versions to me. I hope they'll get a fix released soon.

@eskatos
Copy link
Member

eskatos commented Sep 20, 2023

Adding -XX:-MaxFDLimit to the wrapper script is not enough for it to propagate to the Gradle daemon. It only applies to the Gradle CLI client. Adding it to org.gradle.jvmargs in gradle.properties does set it for the Gradle daemon.

@Rodrigolmti
Copy link
Author

Rodrigolmti commented Sep 20, 2023

This is our current org.gradle.jvmargs:

org.gradle.jvmargs=-XX:-MaxFDLimit -Xmx8g -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 -XX:+UseParallelGC -XX:MaxMetaspaceSize=2g

So, it may not be working, too.

@joshfriend
Copy link

Our fix has been to use a LaunchDaemon to raise the fdlimits at startup:

/opt/local/bin/run_max_files:

#!/bin/sh
# https://developer.apple.com/forums//thread/735798
launchctl limit maxfiles 256 unlimited
launchctl limit maxfiles 128000 524288

/Library/LaunchDaemons/limit.maxfiles.plist:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>Label</key>
	<string>limit.maxfiles</string>
	<key>ProgramArguments</key>
	<array>
		<string>/opt/local/bin/run_max_files</string>
	</array>
	<key>RunAtLoad</key>
	<true/>
</dict>
</plist>

Next, restart or run sudo launchctl load -w /Library/LaunchDaemons/limit.maxfiles.plist. Verify the limit was raised:

$ launchctl limit maxfiles
	maxfiles    128000         524288

We added the following to ./gradlew:

if $darwin; then
    JAVA_OPTS=-XX:-MaxFDLimit
fi 

And ensure that -XX:-MaxFDLimit is in our org.gradle.jvmargs.

@eskatos
Copy link
Member

eskatos commented Sep 22, 2023

Thank you @joshfriend, this works!

@Rodrigolmti
Copy link
Author

Unfortunately, this does not help with our problem. We tested in 2 different machines. Not sure if it is something particular to the project or some constraint to the managed OS by the company.

@eskatos
Copy link
Member

eskatos commented Sep 23, 2023

@Rodrigolmti what doen't work when you apply Josh's recipe? Are your OS and JVM reporting the right limits?
On a managed OS I had to reboot for the limits to apply, launchctl load was denied.

@Rodrigolmti
Copy link
Author

Rodrigolmti commented Sep 26, 2023

Well, the same error still happens (too many open files).

I did try Josh's recipe a couple of times, and double check if everything was right. Even if I restart the computer, I'll get:

maxfiles 256 unlimited

when running:

launchctl limit maxfiles

If I tried to run:

sudo launchctl load -w /Library/LaunchDaemons/limit.maxfiles.plist

I get the following error:

/Library/LaunchDaemons/limit.maxfiles.plist: service already loaded Load failed: 37: Operation already in progress

So I guess it is running.

I have also tried to restart the mac, no luck, a second developer also tried, no luck. Not sure if it can be some restriction of the managed OS because this was working a while ago. I was following this article http://blog.mact.me/2014/10/22/yosemite-upgrade-changes-open-file-limit, however it is not working anymore.

We also tried to run the fileleak-detector, and keeps running out of heap space, we have tested with 12gb of RAM.

@eskatos
Copy link
Member

eskatos commented Sep 27, 2023

If you still get maxfiles 256 unlimited it means you were not able to change your OS limits. If you are using a managed OS, please contact your administrator (I know 😞).

@eskatos
Copy link
Member

eskatos commented Sep 27, 2023

One thing to note is that -XX:-MaxFDLimit is specific to HotSpot JVMs.
I'm not sure it is supported by say J9 VMs. At least a J9 VM I tried did not complain about it.

@Rodrigolmti
Copy link
Author

Rodrigolmti commented Sep 27, 2023

I managed to get it to work by using sudo su commands, however after some builds same problems stills happens:

launchctl limit maxfiles
maxfiles 128000 524288

`
FAILURE: Build failed with an exception.

  • Where:
    Build file '/Users/rodrigo.martins/Code/skipthedishes_android_v3/build.gradle.kts' line: 89

  • What went wrong:
    Unable to parse local Maven settings: /Users/rodrigo.martins/.m2/settings.xml

/Users/rodrigo.martins/.m2/settings.xml (Too many open files)
`

I tried to get a build scan to have more data, but not even the scan works:

Unable to store build scan data: /Users/rodrigo.martins/.gradle/build-scan-data/3.14.1/previous/1695843897568-32947796-6925-4e2c-aff8-78b66b5f3059/scan.scan: Too many open files

I'm at lost with this problem, nothing seems to work. Wondering what can be wrong, but how to understand that if the error messages are not even close to be useful.

One problem that we also see frequently that I think is related to too many open files is:

`
FAILURE: Build completed with 2 failures.

1: Task failed with an exception.

  • Where:
    Build file '/Users/rodrigo.martins/Code/skipthedishes_android_v3/features/customer/consent/concrete/build.gradle.kts' line: 1

  • What went wrong:
    Failed to load compiled script from classpath [/Users/rodrigo.martins/.gradle/caches/8.3/kotlin-dsl/scripts/a04ecaa1e560c7b5ee70980a0b4c9f35/classes->/Users/rodrigo.martins/.gradle/caches/jars-9/2760efb7e80eecfe3a72d8dd5f9dc8aa/classes.jar, /Users/rodrigo.martins/.gradle/caches/8.3/kotlin-dsl/accessors/ef090899837ec2df9bfe8aeaa1bf75d4/classes].

2: Task failed with an exception.

  • What went wrong:
    Failed to stop service 'kotlin-build-service-org.jetbrains.kotlin.gradle.plugin.KotlinGradleBuildServices_1925023691'.

Cannot read the array length because "sessionFiles" is null
`

@joshfriend
Copy link

it is very important that you have -XX:-MaxFDLimit passed to the JVM otherwise hotspot JVMs will continue to use their internal soft limit that does not follow the system limit.

@Rodrigolmti
Copy link
Author

Like I said before:

This is my gradle.properties:

org.gradle.jvmargs=-XX:-MaxFDLimit -Xmx8g -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 -XX:+UseParallelGC -XX:MaxMetaspaceSize=2g

This is my Custom VM options from AS:

-Xmx4096m
-XX:-MaxFDLimit

This is my gradlew file: (Added the exactly same code shared here)

if $darwin; then
    JAVA_OPTS=-XX:-MaxFDLimit
fi

I'm using:

  • JetBrains runtime 17.0.8
  • gradle-8.3
  • Kotlin 1.9.10
  • AGP 8.1.1

A selective workaround is not a workaround. Not sure where else to add this flag.

@Rodrigolmti
Copy link
Author

I manage to get the leak jar working.

localhost.txt

I see a lot of references to /.git folder

Could this be related to this plugin? https://github.com/gladed/gradle-android-git-version. We use it to generate version code / version name based on some git params.

@eskatos
Copy link
Member

eskatos commented Sep 29, 2023

@Rodrigolmti, could very well be that this plugin is not properly closing used resources

@joshfriend
Copy link

If you use Okio/Wire, try using the latest snapshots of Wire which fixes a file descriptor leak (square/okio#1359, https://square.github.io/okio/changelog/#version-360)

There's also fd leak in Detekt: detekt/detekt#6519

Those fixes might help, but for our very large gradle project we still have issues

@pablobaxter
Copy link

If you are seeing the file limit hit while syncing a project on the IDE, you'll also need to add the -XX:-MaxFDLimit to the vmoptions of the IDE. You can edit this file by going to Help -> Edit Custom VM Options...

Our fix has been to use a LaunchDaemon to raise the fdlimits at startup:

/opt/local/bin/run_max_files:

#!/bin/sh
# https://developer.apple.com/forums//thread/735798
launchctl limit maxfiles 256 unlimited
launchctl limit maxfiles 128000 524288

/Library/LaunchDaemons/limit.maxfiles.plist:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>Label</key>
	<string>limit.maxfiles</string>
	<key>ProgramArguments</key>
	<array>
		<string>/opt/local/bin/run_max_files</string>
	</array>
	<key>RunAtLoad</key>
	<true/>
</dict>
</plist>

Next, restart or run sudo launchctl load -w /Library/LaunchDaemons/limit.maxfiles.plist. Verify the limit was raised:

$ launchctl limit maxfiles
	maxfiles    128000         524288

We added the following to ./gradlew:

if $darwin; then
    JAVA_OPTS=-XX:-MaxFDLimit
fi 

And ensure that -XX:-MaxFDLimit is in our org.gradle.jvmargs.

@pablobaxter
Copy link

pablobaxter commented Oct 4, 2023

Took a look at @Rodrigolmti project posted on this issue, and made the following findings using the file leak detector.

Setup:

  • Using -javaagent:file-leak-detector-1.17-jar-with-dependencies.jar=strong,http=19999

  • Tested on 7.4.1

  • Disabled Google Gradle plugins (Firebase, GMS, etc)

  • Steps:

    • Kill all Gradle Daemons
    • Trigger IDE sync on project
    • Download current logs from localhost:19999
    • Trigger IDE sync (5x) on project
    • Download another set of logs from localhost:19999

Results:

After looking at the diffs of the syncs, we can see we have a large number of files that were opened several times with the following stack traces:

#2206 /home/pablo/.gradle/caches/jars-9/a9c9c92df286185f45a06074b5e09e5f/sarif4k-0.0.1.jar by thread:Daemon worker Thread 2 on Tue Oct 03 23:22:03 PDT 2023
#1912 /home/pablo/.gradle/caches/jars-9/a2fea14eaf06a2fd3b5a0a67bdfc619d/android-test-plugin-result-listener-gradle-proto-30.4.2.jar by thread:Daemon worker Thread 2 on Tue Oct 03 23:22:01 PDT 2023
#2883 /home/pablo/.gradle/caches/jars-9/67d7463d6248737c7e580b175e9c7721/android-test-plugin-host-coverage-proto-30.4.2.jar by thread:Daemon worker Thread 2 on Tue Oct 03 23:22:06 PDT 2023
#2539 /home/pablo/.gradle/caches/jars-9/178c949d608cb0abca5adebe84be06dc/kotlin-gradle-plugin-idea-1.7.20.jar by thread:Daemon worker Thread 2 on Tue Oct 03 23:22:04 PDT 2023
#1162 /home/pablo/.gradle/caches/jars-9/1ef4c273d7256c7050bd145298e59562/httpmime-4.5.6.jar by thread:Daemon worker on Tue Oct 03 23:16:48 PDT 2023
#2977 /home/pablo/.gradle/caches/jars-9/09274216b3992984c38353150d6f11e2/netty-common-4.1.52.Final.jar by thread:Daemon worker Thread 2 on Tue Oct 03 23:22:06 PDT 2023
#1126 /home/pablo/.gradle/caches/jars-9/6cee60fe94f704927a4a666d12a24cb9/kotlin-gradle-plugin-api-1.7.20-gradle71.jar by thread:Daemon worker on Tue Oct 03 23:16:48 PDT 2023
#2856 /home/pablo/.gradle/caches/jars-9/25e981fb918f387cfa326975640382c6/kotlinx-serialization-core-jvm-1.1.0.jar by thread:Daemon worker Thread 2 on Tue Oct 03 23:22:06 PDT 2023
#1959 /home/pablo/.gradle/caches/jars-9/d9c734416ccd2cfdda730f29a88fa923/xercesImpl-2.12.0.jar by thread:Daemon worker Thread 2 on Tue Oct 03 23:22:01 PDT 2023
#1983 /home/pablo/.gradle/caches/jars-9/7a96a1563e18bb4b56c336a82fa205ec/perfmark-api-0.23.0.jar by thread:Daemon worker Thread 2 on Tue Oct 03 23:22:01 PDT 2023
#2214 /home/pablo/.gradle/caches/jars-9/9421b75c96db2ab78b95ca4d982e5d81/kotlin-gradle-plugin-idea-proto-1.7.20.jar by thread:Daemon worker Thread 2 on Tue Oct 03 23:22:03 PDT 2023
#2965 /home/pablo/.gradle/caches/jars-9/4df3a82c4cea082f8b5f97d32fafb3fb/listenablefuture-9999.0-empty-to-avoid-conflict-with-guava.jar by thread:Daemon worker Thread 2 on Tue Oct 03 23:22:06 PDT 2023
#1558 /home/pablo/.gradle/caches/jars-9/a9c9c92df286185f45a06074b5e09e5f/sarif4k-0.0.1.jar by thread:Daemon worker Thread 2 on Tue Oct 03 23:21:58 PDT 2023
#2561 /home/pablo/.gradle/caches/jars-9/66beb4694ee1ac7dc128577ca5164b7e/transform-api-2.0.0-deprecated-use-gradle-api.jar by thread:Daemon worker Thread 2 on Tue Oct 03 23:22:04 PDT 2023
#2644 /home/pablo/.gradle/caches/jars-9/fa9ce6fb89d0a674ab54c194e031913f/commons-logging-1.2.jar by thread:Daemon worker Thread 2 on Tue Oct 03 23:22:04 PDT 2023
	at java.base/java.util.zip.ZipFile.<init>(ZipFile.java:173)
	at java.base/java.util.jar.JarFile.<init>(JarFile.java:347)
	at java.base/jdk.internal.loader.URLClassPath$JarLoader.getJarFile(URLClassPath.java:825)
	at java.base/jdk.internal.loader.URLClassPath$JarLoader$1.run(URLClassPath.java:769)
	at java.base/jdk.internal.loader.URLClassPath$JarLoader$1.run(URLClassPath.java:762)
	at java.base/java.security.AccessController.doPrivileged(AccessController.java:712)
	at java.base/jdk.internal.loader.URLClassPath$JarLoader.ensureOpen(URLClassPath.java:761)
	at java.base/jdk.internal.loader.URLClassPath$JarLoader.<init>(URLClassPath.java:735)
	at java.base/jdk.internal.loader.URLClassPath$3.run(URLClassPath.java:499)
	at java.base/jdk.internal.loader.URLClassPath$3.run(URLClassPath.java:482)
	at java.base/java.security.AccessController.doPrivileged(AccessController.java:712)
	at java.base/jdk.internal.loader.URLClassPath.getLoader(URLClassPath.java:481)
	at java.base/jdk.internal.loader.URLClassPath.getLoader(URLClassPath.java:449)
	at java.base/jdk.internal.loader.URLClassPath$1.next(URLClassPath.java:345)
	at java.base/jdk.internal.loader.URLClassPath$1.hasMoreElements(URLClassPath.java:356)
	at java.base/java.net.URLClassLoader$3$1.run(URLClassLoader.java:662)
	at java.base/java.net.URLClassLoader$3$1.run(URLClassLoader.java:660)
	at java.base/java.security.AccessController.doPrivileged(AccessController.java:399)
	at java.base/java.net.URLClassLoader$3.next(URLClassLoader.java:659)
	at java.base/java.net.URLClassLoader$3.hasMoreElements(URLClassLoader.java:684)
	at java.base/java.lang.CompoundEnumeration.next(ClassLoader.java:2725)
	at java.base/java.lang.CompoundEnumeration.hasMoreElements(ClassLoader.java:2734)
	at java.base/java.util.Collections.list(Collections.java:5463)
	at io.gitlab.arturbosch.detekt.extensions.DetektExtensionKt.loadDetektVersion(DetektExtension.kt:110)
	at io.gitlab.arturbosch.detekt.extensions.DetektExtension.<init>(DetektExtension.kt:14)
	at io.gitlab.arturbosch.detekt.extensions.DetektExtension_Decorated.<init>(Unknown Source)

This shows that you are dealing with the detekt leak fixed here: detekt/detekt#6519

However, I also saw this other leak occurring in the Kotlin script evaluator code:

#2138 /home/pablo/.gradle/caches/jars-9/6af4e5a00a5c12aff4f3e60329c2e3ce/netty-codec-http2-4.1.34.Final.jar by thread:Daemon worker Thread 2 on Tue Oct 03 23:22:03 PDT 2023
#2360 /home/pablo/.gradle/caches/jars-9/2bccfabc9627dce75dfec0a81ac0f718/tracker-30.2.2.jar by thread:Daemon worker Thread 2 on Tue Oct 03 23:22:04 PDT 2023
#810 /home/pablo/.gradle/caches/jars-9/200dc75d56888988c020f05d1acd2f4a/databinding-compiler-common-7.2.2.jar by thread:Daemon worker on Tue Oct 03 23:16:48 PDT 2023
#1795 /home/pablo/.gradle/caches/jars-9/37e86d11f8f17bd0bab59dabd0958a3c/markdown-jvm-0.2.1.jar by thread:Daemon worker Thread 2 on Tue Oct 03 23:22:01 PDT 2023
#2096 /home/pablo/.gradle/caches/jars-9/e6b42593426426129fbf49f296b66d5a/kotlin-annotation-processing-gradle-1.7.20.jar by thread:Daemon worker Thread 2 on Tue Oct 03 23:22:03 PDT 2023
#2792 /home/pablo/.gradle/caches/jars-9/c001dfeb0c90cbd3bfd566ee5c398190/commons-codec-1.11.jar by thread:Daemon worker Thread 2 on Tue Oct 03 23:22:06 PDT 2023
#1413 /home/pablo/.gradle/caches/jars-9/4a1ca8cfbb64d9629d5985a012f9c0fe/asm-commons-9.1.jar by thread:Daemon worker Thread 2 on Tue Oct 03 23:21:58 PDT 2023
#1503 /home/pablo/.gradle/caches/jars-9/58eb10a7c81d9403d81eab7bbfb9fb0f/jsr305-3.0.2.jar by thread:Daemon worker Thread 2 on Tue Oct 03 23:21:58 PDT 2023
#1443 /home/pablo/.gradle/caches/jars-9/178c949d608cb0abca5adebe84be06dc/kotlin-gradle-plugin-idea-1.7.20.jar by thread:Daemon worker Thread 2 on Tue Oct 03 23:21:58 PDT 2023
#2820 /home/pablo/.gradle/caches/jars-9/582fa49ce9b29e83dda1268ce47be0c9/netty-common-4.1.34.Final.jar by thread:Daemon worker Thread 2 on Tue Oct 03 23:22:06 PDT 2023
#2089 /home/pablo/.gradle/caches/jars-9/6cee60fe94f704927a4a666d12a24cb9/kotlin-gradle-plugin-api-1.7.20-gradle71.jar by thread:Daemon worker Thread 2 on Tue Oct 03 23:22:03 PDT 2023
	at java.base/java.util.zip.ZipFile.<init>(ZipFile.java:173)
	at java.base/java.util.jar.JarFile.<init>(JarFile.java:347)
	at java.base/jdk.internal.loader.URLClassPath$JarLoader.getJarFile(URLClassPath.java:825)
	at java.base/jdk.internal.loader.URLClassPath$JarLoader$1.run(URLClassPath.java:769)
	at java.base/jdk.internal.loader.URLClassPath$JarLoader$1.run(URLClassPath.java:762)
	at java.base/java.security.AccessController.doPrivileged(AccessController.java:712)
	at java.base/jdk.internal.loader.URLClassPath$JarLoader.ensureOpen(URLClassPath.java:761)
	at java.base/jdk.internal.loader.URLClassPath$JarLoader.<init>(URLClassPath.java:735)
	at java.base/jdk.internal.loader.URLClassPath$3.run(URLClassPath.java:499)
	at java.base/jdk.internal.loader.URLClassPath$3.run(URLClassPath.java:482)
	at java.base/java.security.AccessController.doPrivileged(AccessController.java:712)
	at java.base/jdk.internal.loader.URLClassPath.getLoader(URLClassPath.java:481)
	at java.base/jdk.internal.loader.URLClassPath.getLoader(URLClassPath.java:449)
	at java.base/jdk.internal.loader.URLClassPath.getResource(URLClassPath.java:318)
	at java.base/java.net.URLClassLoader$1.run(URLClassLoader.java:424)
	at java.base/java.net.URLClassLoader$1.run(URLClassLoader.java:421)
	at java.base/java.security.AccessController.doPrivileged(AccessController.java:712)
	at java.base/java.net.URLClassLoader.findClass(URLClassLoader.java:420)
	at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:587)
	at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:574)
	at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:520)
	at org.gradle.kotlin.dsl.provider.StandardKotlinScriptEvaluator$ScopeBackedCompiledScript.getProgram(KotlinScriptEvaluator.kt:300)
	at org.gradle.kotlin.dsl.execution.Interpreter$ProgramHost.load(Interpreter.kt:539)
	at org.gradle.kotlin.dsl.execution.Interpreter$ProgramHost.eval(Interpreter.kt:529)
	at org.gradle.kotlin.dsl.execution.Interpreter.eval(Interpreter.kt:205)
	at org.gradle.kotlin.dsl.provider.StandardKotlinScriptEvaluator.evaluate(KotlinScriptEvaluator.kt:115)
	at org.gradle.kotlin.dsl.provider.KotlinScriptPluginFactory$create$1.invoke(KotlinScriptPluginFactory.kt:51)
	at org.gradle.kotlin.dsl.provider.KotlinScriptPluginFactory$create$1.invoke(KotlinScriptPluginFactory.kt:36)
	at org.gradle.kotlin.dsl.provider.KotlinScriptPlugin.apply(KotlinScriptPlugin.kt:34)
	at org.gradle.configuration.BuildOperationScriptPlugin$1.run(BuildOperationScriptPlugin.java:65)

But investigating this further, if we upgrade to using Gradle 8.3, we get the following results:

As we can see, the increase in file descriptors isn't as much as 7.4.1. Also, comparing these two files, we can see the detekt bug is still there too. However, the Kotlin script evaluator leak is not seen here, instead, there is a minor leak here:

#1404 /home/pablo/.gradle/caches/jars-9/cb496670261697cd042dd38d366ec96f/cp_init.jar by thread:Daemon worker on Tue Oct 03 23:38:40 PDT 2023
#637 /home/pablo/.gradle/caches/jars-9/6b3f37ba26f974b455636c5d2117a05a/cp_init.jar by thread:Daemon worker on Tue Oct 03 23:38:00 PDT 2023
#1412 /home/pablo/.gradle/caches/jars-9/3d52d794dcad9a58d0382041810c66f0/cp_init.jar by thread:Daemon worker on Tue Oct 03 23:38:42 PDT 2023
#642 /home/pablo/.gradle/caches/jars-9/7b4e0b4012a51a94e093a6ba8f20d833/cp_init.jar by thread:Daemon worker on Tue Oct 03 23:38:00 PDT 2023
#1420 /home/pablo/.gradle/caches/jars-9/4b99d2e4bbd1db8bb30bf734fad67d08/cp_init.jar by thread:Daemon worker on Tue Oct 03 23:38:43 PDT 2023
#1388 /home/pablo/.gradle/caches/jars-9/14c0d3108ef48a2238843e2cf042be64/cp_init.jar by thread:Daemon worker on Tue Oct 03 23:38:38 PDT 2023
#1396 /home/pablo/.gradle/caches/jars-9/13e9bfd682e5e65831a83a16d3cdae13/cp_init.jar by thread:Daemon worker on Tue Oct 03 23:38:39 PDT 2023
	at java.base/java.util.zip.ZipFile.<init>(ZipFile.java:173)
	at java.base/java.util.jar.JarFile.<init>(JarFile.java:347)
	at java.base/jdk.internal.loader.URLClassPath$JarLoader.getJarFile(URLClassPath.java:825)
	at java.base/jdk.internal.loader.URLClassPath$JarLoader$1.run(URLClassPath.java:769)
	at java.base/jdk.internal.loader.URLClassPath$JarLoader$1.run(URLClassPath.java:762)
	at java.base/java.security.AccessController.doPrivileged(AccessController.java:712)
	at java.base/jdk.internal.loader.URLClassPath$JarLoader.ensureOpen(URLClassPath.java:761)
	at java.base/jdk.internal.loader.URLClassPath$JarLoader.<init>(URLClassPath.java:735)
	at java.base/jdk.internal.loader.URLClassPath$3.run(URLClassPath.java:499)
	at java.base/jdk.internal.loader.URLClassPath$3.run(URLClassPath.java:482)
	at java.base/java.security.AccessController.doPrivileged(AccessController.java:712)
	at java.base/jdk.internal.loader.URLClassPath.getLoader(URLClassPath.java:481)
	at java.base/jdk.internal.loader.URLClassPath.getLoader(URLClassPath.java:449)
	at java.base/jdk.internal.loader.URLClassPath.getResource(URLClassPath.java:318)
	at java.base/java.net.URLClassLoader$1.run(URLClassLoader.java:424)
	at java.base/java.net.URLClassLoader$1.run(URLClassLoader.java:421)
	at java.base/java.security.AccessController.doPrivileged(AccessController.java:712)
	at java.base/java.net.URLClassLoader.findClass(URLClassLoader.java:420)
	at org.gradle.groovy.scripts.internal.DefaultScriptCompilationHandler$ScriptClassLoader.loadClass(DefaultScriptCompilationHandler.java:384)
	at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:520)
	at org.gradle.groovy.scripts.internal.DefaultScriptCompilationHandler$ClassesDirCompiledScript.loadClass(DefaultScriptCompilationHandler.java:335)
	at org.gradle.groovy.scripts.internal.DefaultScriptRunnerFactory$ScriptRunnerImpl.getScript(DefaultScriptRunnerFactory.java:55)
	at org.gradle.groovy.scripts.internal.DefaultScriptRunnerFactory$ScriptRunnerImpl.run(DefaultScriptRunnerFactory.java:86)
	at org.gradle.configuration.DefaultScriptPluginFactory$ScriptPluginImpl.apply(DefaultScriptPluginFactory.java:111)
	at org.gradle.configuration.BuildOperationScriptPlugin$1.run(BuildOperationScriptPlugin.java:65)

This seems to affect the files for cp_init.jar and init.jar, which I'm assuming are the build script binaries. However, I would only assume they would be opened once per configuration of a build. @jbartok I'm wondering if this is something actionable on your end?

As for @Rodrigolmti, I would recommend migrating to Gradle 8.3.0, and fixing your Mpp.kt class in your buildsrc directory, as the input stream there is not being closed properly. You can see the leak here:

#1424 local.properties by thread:Daemon worker on Tue Oct 03 23:38:43 PDT 2023
#1400 local.properties by thread:Daemon worker on Tue Oct 03 23:38:39 PDT 2023
#1408 local.properties by thread:Daemon worker on Tue Oct 03 23:38:41 PDT 2023
#1416 local.properties by thread:Daemon worker on Tue Oct 03 23:38:42 PDT 2023
#1392 local.properties by thread:Daemon worker on Tue Oct 03 23:38:38 PDT 2023
	at java.base/java.io.FileInputStream.<init>(FileInputStream.java:159)
	at Mpp.getDir(Mpp.kt:8)
	at Build_gradle.<init>(build.gradle.kts:30)
	at Program.execute(Unknown Source)
	at org.gradle.kotlin.dsl.execution.Interpreter$ProgramHost.eval(Interpreter.kt:523)
	at org.gradle.kotlin.dsl.execution.Interpreter$ProgramHost.evaluateSecondStageOf(Interpreter.kt:434)
	at Program.execute(Unknown Source)
	at org.gradle.kotlin.dsl.execution.Interpreter$ProgramHost.eval(Interpreter.kt:523)
	at org.gradle.kotlin.dsl.execution.Interpreter.eval(Interpreter.kt:198)
	at org.gradle.kotlin.dsl.provider.StandardKotlinScriptEvaluator.evaluate(KotlinScriptEvaluator.kt:121)
	at org.gradle.kotlin.dsl.provider.KotlinScriptPluginFactory$create$1.invoke(KotlinScriptPluginFactory.kt:51)
	at org.gradle.kotlin.dsl.provider.KotlinScriptPluginFactory$create$1.invoke(KotlinScriptPluginFactory.kt:48)
	at org.gradle.kotlin.dsl.provider.KotlinScriptPlugin.apply(KotlinScriptPlugin.kt:35)
	at org.gradle.configuration.BuildOperationScriptPlugin$1.run(BuildOperationScriptPlugin.java:65)

@pablobaxter
Copy link

pablobaxter commented Oct 4, 2023

The TL;DR for the above:

Detekt was one reason for the original file leak, but it seems there's some weird file leak happening in Gradle 7.4.1 with the Kotlin script evaluator. That Kotlin evaluator bug goes away(?) with Gradle 8.3, but then we see other smaller leaks with script evaluation too. Finally, there is one small leak in the project code buildsrc.

I believe this issue isn't shown right away, but after several builds/syncs. I only tested this for the configuration phase, but it's entirely possible to see file leaks occur in the build phase as well, which will also trigger the Too many open files issue.

@eskatos
Copy link
Member

eskatos commented Oct 4, 2023

cp_init.jar and init.jar would be for Groovy DSL scripts. I don't see any .gradle script in the tested project. Could it be some init scripts? possibly in your Gradle User Home? or maybe injected by the IDE.

IIRC, the Groovy DSL keeps these files open across builds if they are reused, and should release them if two consecutive builds are not reusing them. If these are coming from temporary init scripts injected by the IDE with changing path/names on each invocation it might trigger a slow fd leak.

@pablobaxter
Copy link

pablobaxter commented Oct 4, 2023

I don't have any init scripts in my Gradle User Home, but I did use IntelliJ to trigger the Gradle sync, which is probably where these scripts are coming from then. I made no changes to the project, only hit the "sync" button back to back.

Doing a count of the extra jars opened, it's exactly 5 extra file descriptors for each stack trace, which coincides with my testing. Each new file sits in a different directory than the others.

Screenshot from 2023-10-04 08-56-19

I believe you are correct @eskatos, this seems to be an IntelliJ file leak. I can file this bug with the Jetbrains team.

Edit:
Tested on an an open source of mine (https://github.com/pablobaxter/Harmony), and didn't see the increase in open files upon several syncs. IntelliJ does use a temp directory to store their init-scripts before passing them off to the daemon (code for this logic here), but these files are reused, so they aren't new files generated each run (verified on IntelliJ master branch). If my curiosity gets the better of me, I will dig further on the issue this evening to understand why.

@Rodrigolmti
Copy link
Author

Rodrigolmti commented Oct 4, 2023

Hmn that's fascinating, thanks for the investigation. Right now we are using Gradle 8.3 already, and indeed, we notice some improvements, We'll try to fix the leak for the MPP and wait for the detekt new version and post the update here.

Really appreciate all the help.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
a:bug has:reproducer Indicates the issue has a confirmed reproducer has:workaround Indicates that the issue has a workaround in:daemon in:wrapper
Projects
None yet
Development

No branches or pull requests

6 participants