Applications stuck in UDP sendto syscall

Hi,

We’re seeing our build system (Gradle) get stuck in sendto system calls while trying to communicate with other processes via the local interface over UDP. To the end user it appears that the build is stuck or they will receive an error “Timeout waiting to lock XXX. It is currently in use by another Gradle instance”. But when the process is sampled/profiled, we can see one of the threads is stuck in a sendto system call. The only way to resolve the issue is to kill -s KILL <pid> the stuck Gradle process.

A part of the JVM level stack trace:

"jar transforms Thread 12" #90 prio=5 os_prio=31 cpu=0.85ms elapsed=1257.67s tid=0x000000012e6cd400 nid=0x10f03 runnable  [0x0000000332f0d000]
   java.lang.Thread.State: RUNNABLE
        at sun.nio.ch.DatagramChannelImpl.send0(java.base@17.0.10/Native Method)
        at sun.nio.ch.DatagramChannelImpl.sendFromNativeBuffer(java.base@17.0.10/DatagramChannelImpl.java:901)
        at sun.nio.ch.DatagramChannelImpl.send(java.base@17.0.10/DatagramChannelImpl.java:863)
        at sun.nio.ch.DatagramChannelImpl.send(java.base@17.0.10/DatagramChannelImpl.java:821)
        at sun.nio.ch.DatagramChannelImpl.blockingSend(java.base@17.0.10/DatagramChannelImpl.java:853)
        at sun.nio.ch.DatagramSocketAdaptor.send(java.base@17.0.10/DatagramSocketAdaptor.java:218)
        at java.net.DatagramSocket.send(java.base@17.0.10/DatagramSocket.java:664)
        at org.gradle.cache.internal.locklistener.FileLockCommunicator.pingOwner(FileLockCommunicator.java:61)
        at org.gradle.cache.internal.locklistener.DefaultFileLockContentionHandler.maybePingOwner(DefaultFileLockContentionHandler.java:203)
        at org.gradle.cache.internal.DefaultFileLockManager$DefaultFileLock$1.run(DefaultFileLockManager.java:380)
        at org.gradle.internal.io.ExponentialBackoff.retryUntil(ExponentialBackoff.java:72)
        at org.gradle.cache.internal.DefaultFileLockManager$DefaultFileLock.lockStateRegion(DefaultFileLockManager.java:362)
        at org.gradle.cache.internal.DefaultFileLockManager$DefaultFileLock.lock(DefaultFileLockManager.java:293)
        at org.gradle.cache.internal.DefaultFileLockManager$DefaultFileLock.<init>(DefaultFileLockManager.java:164)
        at org.gradle.cache.internal.DefaultFileLockManager.lock(DefaultFileLockManager.java:110)
        at org.gradle.cache.internal.LockOnDemandCrossProcessCacheAccess.incrementLockCount(LockOnDemandCrossProcessCacheAccess.java:106)
        at org.gradle.cache.internal.LockOnDemandCrossProcessCacheAccess.acquireFileLock(LockOnDemandCrossProcessCacheAccess.java:168)
        at org.gradle.cache.internal.CrossProcessSynchronizingCache.put(CrossProcessSynchronizingCache.java:57)
        at org.gradle.api.internal.changedetection.state.DefaultFileAccessTimeJournal.setLastAccessTime(DefaultFileAccessTimeJournal.java:85)
        at org.gradle.internal.file.impl.SingleDepthFileAccessTracker.markAccessed(SingleDepthFileAccessTracker.java:51)
        at org.gradle.internal.classpath.DefaultCachedClasspathTransformer.markAccessed(DefaultCachedClasspathTransformer.java:209)
        at org.gradle.internal.classpath.DefaultCachedClasspathTransformer.transformFile(DefaultCachedClasspathTransformer.java:194)
        at org.gradle.internal.classpath.DefaultCachedClasspathTransformer.lambda$cachedFile$6(DefaultCachedClasspathTransformer.java:186)
        at org.gradle.internal.classpath.DefaultCachedClasspathTransformer$$Lambda$368/0x0000007001393a78.call(Unknown Source)
        at org.gradle.internal.UncheckedException.unchecked(UncheckedException.java:74)
        at org.gradle.internal.classpath.DefaultCachedClasspathTransformer.lambda$transformAll$8(DefaultCachedClasspathTransformer.java:233)
        at org.gradle.internal.classpath.DefaultCachedClasspathTransformer$$Lambda$372/0x0000007001398470.call(Unknown Source)
        at java.util.concurrent.FutureTask.run(java.base@17.0.10/FutureTask.java:264)
        at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:64)
        at org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:49)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(java.base@17.0.10/ThreadPoolExecutor.java:1136)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(java.base@17.0.10/ThreadPoolExecutor.java:635)
        at java.lang.Thread.run(java.base@17.0.10/Thread.java:840)

A part of the process sample:

    2097 Thread_3879661: Java: jar transforms Thread 12
    + 2097 thread_start  (in libsystem_pthread.dylib) + 8  [0x18c42eb80]

...removed for brevity...

    +                                                                     2097 Java_sun_nio_ch_DatagramChannelImpl_send0  (in libnio.dylib) + 84  [0x102ef371c]
    +                                                                       2097 __sendto  (in libsystem_kernel.dylib) + 8  [0x18c3f612c]

We have observed the following system logs around the time the issue manifests:

2025-08-26 22:03:23.280255+0100 0x3b2c00   Default     0x0                  0      0    kernel: cfil_hash_entry_log:6088 <CFIL: Error: sosend_reinject() failed>: [4628 java] <UDP(17) in so 9e934ceda1c13379 50826943645358435 50826943645358435 ag>
2025-08-26 22:03:23.280267+0100 0x3b2c00   Default     0x0                  0      0    kernel: cfil_service_inject_queue:4472 CFIL: sosend() failed 22

The issue seems to be rooted in the built-in Application Firewall, as disabling it “fixes” the issue. It doesn’t seem to matter that the process is on the “allow” list.

We’re using Gradle 7.6.4, 8.0.2 and 8.14.1 in various repositories, so the version doesn’t seem to matter, neither does which repo we use.

The most reliable way to reproduce is to run two Gradle builds at the same time or very quickly after each other.

We would really appreciate a fix for this as it really negatively affects the developer experience. I've raised FB19916240 for this.

Many thanks,

Answered by DTS Engineer in 855668022
I've raised FB19916240 for this.

Thanks. A bug report is the best path forward here.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

I've raised FB19916240 for this.

Thanks. A bug report is the best path forward here.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Applications stuck in UDP sendto syscall
 
 
Q