Gradle worker 在 macOS 沙箱里连不上 daemon,核对 IPv4 参数
Gradle 9.7.0 的进程隔离 worker 可能被 macOS 沙箱拦住双栈回连。为可控的 processIsolation 单独设置 JVM IPv4 参数,同时确认该 worker 不依赖 IPv6。
macOS 上把 Gradle 放进 SBPL 沙箱后,普通测试仍能运行,使用 WorkerExecutor.processIsolation 的插件却无法让 worker 连回 Gradle daemon。若沙箱拒绝 IPv6,要检查独立 worker 实际启动时的网络参数;不能只看顶层 Gradle 已经读到了 JAVA_TOOL_OPTIONS。
这类情形在 Gradle 9.1.0、9.7.0 的进程隔离 worker 中出现,也有更早版本的相同表现。它不是所有 Gradle worker 停顿的解释。worker 数量耗尽、下载阻塞和任务自身等待,都需要另外定位。
127.0.0.1 也可能走双栈套接字
进程隔离的工作动作运行在另一台 JVM 中,需要通过 Gradle 的本机通信通道回连。JDK 默认的双栈套接字可以把 IPv4 loopback 表现为 ::ffff:127.0.0.1。因此,配置里看到 127.0.0.1,仍不能据此认定操作系统和沙箱一定只看到了 IPv4 连接。
若沙箱拒绝了这条 IPv4-mapped IPv6 回连,增加任务超时不会放通它。先保留沙箱拒绝日志、worker 启动日志和原 JVM 参数,确认拒绝发生在 worker 自身的本机回连,而非工作动作正在访问的业务地址。
顶层 daemon、Test 任务 JVM 与 processIsolation worker 有不同的启动入口。org.gradle.jvmargs 或 Test 任务上的设置不能自动视为已经配置了这个 worker。把所有现有 JAVA_TOOL_OPTIONS 原样转发,也会连同 agent、调试参数等其他内容一起改变子进程。
只为能够配置的 worker 设置启动参数
对于自己的插件或暴露了 worker forkOptions 配置的任务,可在原 processIsolation 创建位置加入一项 JVM 参数。下面是任务方法中的 Kotlin DSL 局部代码,workerExecutor 是已有注入对象;保留随后原有的 submit、参数赋值及等待流程:
val queue = workerExecutor.processIsolation {
forkOptions {
jvmArgs("-Djava.net.preferIPv4Stack=true")
}
}
该属性需要在 worker JVM 启动时传入。在任务动作内部调用 System.setProperty,不能等同于选择该 JVM 初始使用的套接字栈。Gradle 9.7.0 的进程 worker 路径会将这里的 Java fork options 复制到实际 Java 启动命令。
已有 fork options 中的堆大小、系统属性和其他必需参数应保留,不要用一份新的参数列表覆盖它们。第三方插件没有公开这个入口时,应使用它支持的配置或兼容的已发布插件版本;不能假定在任意 build.gradle.kts 里创建一个未被使用的队列,就能改变插件内部的 worker。
这会影响该 worker 的全部 IPv6 网络
java.net.preferIPv4Stack=true 作用于整个 worker JVM,不只作用于 Gradle IPC。工作动作若必须访问仅有 IPv6 地址的服务器,这个选择可能让那部分功能失败。应先确认该 worker 的网络需求和实际地址,再决定是否适合采用。
这项局部调整也不会为沙箱增加本来没有的 IPv4 loopback 权限。若拒绝日志明确是 IPv4 回连,或者没有相应网络拒绝证据,应继续核对沙箱已有规则和 worker 启动失败原因,不要反复切换地址族。不要为让构建变绿关闭整个沙箱或放宽全部网络访问。
采用参数后,检查新启动 worker 的 JVM 命令行,再运行原来失败的插件任务,确认工作动作完成且产物正确。还要覆盖该 worker 原有的网络调用,尤其是 IPv6 依赖。保留原 fork options 便于撤回;单独看到 daemon 或测试 JVM 正常,仍没有验收到实际受影响的 worker。


