1 Star 0 Fork 81

zhaosai/openjdk-1.8.0

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
0002-8179498-attach-in-linux-should-be-relative-to-proc-p.patch 5.88 KB
一键复制 编辑 原始数据 按行查看 历史
Date: Tue, 30 May 2023 03:43:28 +0000
Subject: [PATCH 02/59] 8179498: attach in linux should be relative to
/proc/pid/root and namespace aware
Bug url: https://bugs.openjdk.org/browse/JDK-8179498
---
.../sun/tools/attach/LinuxVirtualMachine.java | 70 ++++++++++++++++---
1 file changed, 62 insertions(+), 8 deletions(-)
diff --git a/jdk/src/solaris/classes/sun/tools/attach/LinuxVirtualMachine.java b/jdk/src/solaris/classes/sun/tools/attach/LinuxVirtualMachine.java
index 20fdb5c0d..cc2ac0df2 100644
--- a/jdk/src/solaris/classes/sun/tools/attach/LinuxVirtualMachine.java
+++ b/jdk/src/solaris/classes/sun/tools/attach/LinuxVirtualMachine.java
@@ -32,6 +32,10 @@ import com.sun.tools.attach.spi.AttachProvider;
import java.io.InputStream;
import java.io.IOException;
import java.io.File;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.Files;
/*
* Linux implementation of HotSpotVirtualMachine
@@ -66,12 +70,15 @@ public class LinuxVirtualMachine extends HotSpotVirtualMachine {
throw new AttachNotSupportedException("Invalid process identifier");
}
+ // Try to resolve to the "inner most" pid namespace
+ int ns_pid = getNamespacePid(pid);
+
// Find the socket file. If not found then we attempt to start the
// attach mechanism in the target VM by sending it a QUIT signal.
// Then we attempt to find the socket file again.
- path = findSocketFile(pid);
+ path = findSocketFile(pid, ns_pid);
if (path == null) {
- File f = createAttachFile(pid);
+ File f = createAttachFile(pid, ns_pid);
try {
// On LinuxThreads each thread is a process and we don't have the
// pid of the VMThread which has SIGQUIT unblocked. To workaround
@@ -99,7 +106,7 @@ public class LinuxVirtualMachine extends HotSpotVirtualMachine {
try {
Thread.sleep(delay);
} catch (InterruptedException x) { }
- path = findSocketFile(pid);
+ path = findSocketFile(pid, ns_pid);
i++;
} while (i <= retries && path == null);
if (path == null) {
@@ -272,8 +279,12 @@ public class LinuxVirtualMachine extends HotSpotVirtualMachine {
}
// Return the socket file for the given process.
- private String findSocketFile(int pid) {
- File f = new File(tmpdir, ".java_pid" + pid);
+ private String findSocketFile(int pid, int ns_pid) {
+ // A process may not exist in the same mount namespace as the caller.
+ // Instead, attach relative to the target root filesystem as exposed by
+ // procfs regardless of namespaces.
+ String root = "/proc/" + pid + "/root/" + tmpdir;
+ File f = new File(root, ".java_pid" + ns_pid);
if (!f.exists()) {
return null;
}
@@ -284,14 +295,23 @@ public class LinuxVirtualMachine extends HotSpotVirtualMachine {
// if not already started. The client creates a .attach_pid<pid> file in the
// target VM's working directory (or temp directory), and the SIGQUIT handler
// checks for the file.
- private File createAttachFile(int pid) throws IOException {
- String fn = ".attach_pid" + pid;
+ private File createAttachFile(int pid, int ns_pid) throws IOException {
+ String fn = ".attach_pid" + ns_pid;
String path = "/proc/" + pid + "/cwd/" + fn;
File f = new File(path);
try {
f.createNewFile();
} catch (IOException x) {
- f = new File(tmpdir, fn);
+ String root;
+ if (pid != ns_pid) {
+ // A process may not exist in the same mount namespace as the caller.
+ // Instead, attach relative to the target root filesystem as exposed by
+ // procfs regardless of namespaces.
+ root = "/proc/" + pid + "/root/" + tmpdir;
+ } else {
+ root = tmpdir;
+ }
+ f = new File(root, fn);
f.createNewFile();
}
return f;
@@ -317,6 +337,40 @@ public class LinuxVirtualMachine extends HotSpotVirtualMachine {
}
+ // Return the inner most namespaced PID if there is one,
+ // otherwise return the original PID.
+ private int getNamespacePid(int pid) throws AttachNotSupportedException, IOException {
+ // Assuming a real procfs sits beneath, reading this doesn't block
+ // nor will it consume a lot of memory.
+ String statusFile = "/proc/" + pid + "/status";
+ File f = new File(statusFile);
+ if (!f.exists()) {
+ return pid; // Likely a bad pid, but this is properly handled later.
+ }
+
+ Path statusPath = Paths.get(statusFile);
+
+ try {
+ for (String line : Files.readAllLines(statusPath, StandardCharsets.UTF_8)) {
+ String[] parts = line.split(":");
+ if (parts.length == 2 && parts[0].trim().equals("NSpid")) {
+ parts = parts[1].trim().split("\\s+");
+ // The last entry represents the PID the JVM "thinks" it is.
+ // Even in non-namespaced pids these entries should be
+ // valid. You could refer to it as the inner most pid.
+ int ns_pid = Integer.parseInt(parts[parts.length - 1]);
+ return ns_pid;
+ }
+ }
+ // Old kernels may not have NSpid field (i.e. 3.10).
+ // Fallback to original pid in the event we cannot deduce.
+ return pid;
+ } catch (NumberFormatException | IOException x) {
+ throw new AttachNotSupportedException("Unable to parse namespace");
+ }
+ }
+
+
//-- native methods
static native boolean isLinuxThreads();
--
2.22.0
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/zhaosai-Simon/openjdk-1.8.0.git
git@gitee.com:zhaosai-Simon/openjdk-1.8.0.git
zhaosai-Simon
openjdk-1.8.0
openjdk-1.8.0
master

搜索帮助