RFR: 8373867: Improve robustness of Attach API for finding tmp directory [v5]
Yasumasa Suenaga
ysuenaga at openjdk.org
Mon Jan 19 10:58:49 UTC 2026
On Wed, 7 Jan 2026 04:27:46 GMT, Yasumasa Suenaga <ysuenaga at openjdk.org> wrote:
>> We can see several thread dump on the console of Distroless nonroot JDK when we attach debug (root) Distroless container image to the nonroot container as following. It is not expected.
>>
>>
>> $ podman run -it --rm --name debuggee -v `pwd`/LongSleep:/opt/LongSleep:Z --entrypoint java gcr.io/distroless/java25-debian13:nonroot -cp /opt/LongSleep -Xlog:attach=debug LongSleep
>> [38.252s][debug][attach] Failed to find attach file: /tmp/.attach_pid1
>> 2025-12-17 06:34:37
>> Full thread dump OpenJDK 64-Bit Server VM (25.0.1+8-LTS mixed mode, sharing):
>>
>> Threads class SMR info:
>> _java_thread_list=0x000078a8bc13f200, length=10, elements={
>> 0x000078a8bc02bb60, 0x000078a8bc128200, 0x000078a8bc1293f0, 0x000078a8bc12ae40,
>> 0x000078a8bc12c760, 0x000078a8bc12dfe0, 0x000078a8bc12fde0, 0x000078a8bc1317d0,
>> :
>>
>>
>> Attach API put `.attach_pid<pid>` file at first to clarify subsequent SIGQUIT means create AttachListener thread. That file attempt to create on current work directory of the target process, but it would fallback to /tmp if failed (e.g. attacher cannot write onto work directory).
>>
>> In case of attaching nonroot container from root container, and also it would fail due to lack of write permission on current work directory, and cannot access /proc/<PID>/root/tmp. It causes following error on jcmd:
>>
>>
>> $ podman run -it --rm --pid container:debuggee --entrypoint sh gcr.io/distroless/java25-debian13:debug
>> / # /usr/lib/jvm/jcmd 1 VM.version
>> 1:
>> com.sun.tools.attach.AttachNotSupportedException: Unable to open socket file /tmp/.java_pid1: target process 1 doesn't respond within 10500ms or HotSpot VM not loaded
>> at jdk.attach/sun.tools.attach.VirtualMachineImpl.<init>(VirtualMachineImpl.java:115)
>> at jdk.attach/sun.tools.attach.AttachProviderImpl.attachVirtualMachine(AttachProviderImpl.java:56)
>> at jdk.attach/com.sun.tools.attach.VirtualMachine.attach(VirtualMachine.java:201)
>> at jdk.jcmd/sun.tools.jcmd.JCmd.executeCommandForPid(JCmd.java:113)
>> at jdk.jcmd/sun.tools.jcmd.JCmd.main(JCmd.java:97)
>>
>> / # ls -l /proc/1/cwd
>> ls: /proc/1/cwd: cannot read link: Permission denied
>> lrwxrwxrwx 1 nonroot nonroot 0 Dec 17 06:34 /proc/1/cwd
>>
>>
>>
>> After this change, we can see following exception on the console of jcmd when we encounter this situation:
>>
>> # jcmd 1 VM.version
>> 1:
>> com.sun.tools.attach.AttachNotSupportedException: Unable to access the filesystem of the target process
>> at jdk.attac...
>
> Yasumasa Suenaga has updated the pull request incrementally with two additional commits since the last revision:
>
> - Fix line
> - Update copyright year
I think we cannot remove `catch` for IOException because it is used for fallback code.
I added numbers as comment to the code to explain:
try {
if (Files.isWritable(tmpOnProcPidRoot)) {
return tmpOnProcPidRoot.toString();
} else if (Files.isSameFile(tmpOnProcPidRoot, TMPDIR)) { // <- (1)
return TMPDIR.toString();
} else {
throw new AttachNotSupportedException("Unable to access the filesystem of the target process"); // <- (2)
}
} catch (IOException ioe) {
try {
boolean found = MonitoredHost.getMonitoredHost("//localhost")
.activeVms()
.stream()
.anyMatch(i -> pid == i.intValue());
if (found) {
// We can use /tmp because target process is on same host
// even if we cannot access /proc/<PID>/root.
// The process with capsh/setcap would fall this pattern.
return TMPDIR.toString();
}
// Throw original IOE if target process not found on localhost.
throw ioe; // <- (3)
} catch (MonitorException | URISyntaxException e) { // <- (4)
// Other exceptions (happened at MonitoredHost) would be wrapped with AttachNotSupportedException
throw new AttachNotSupportedException("Unable to find target proces", e);
}
}
1. AccessDeniedException might be thrown if the process is not granted to access the path. In addition, other exceptions which inherits IOException would be thrown I/O error (e.g. disconnection of network file system)
2. If `/proc/<pid>/root/tmp` is not writable and it is different from `/tmp`, AttachNotSupportedException is thrown. It would be happened in container, or jailed process (chroot). I think that target process can be considered to be running in an environment that does not support Attach API.
3. If IOException is happened at `Files.isSame()`, Attach API attempts to check whether target process (PID) is listed in active VMs in `MonitoredHost`. Throws original IOException if not.
4. Methods in `MonitoredHost` might throw `MonitorException` or `URISyntaxException`.
-------------
PR Comment: https://git.openjdk.org/jdk/pull/28867#issuecomment-3767711293
More information about the serviceability-dev
mailing list