Projects
openEuler:24.03:SP1:Everything
openjdk-1.8.0
_service:tar_scm:0002-8179498-attach-in-linux-s...
Sign Up
Log In
Username
Password
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File _service:tar_scm:0002-8179498-attach-in-linux-should-be-relative-to-proc-p.patch of Package openjdk-1.8.0
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
Locations
Projects
Search
Status Monitor
Help
Open Build Service
OBS Manuals
API Documentation
OBS Portal
Reporting a Bug
Contact
Mailing List
Forums
Chat (IRC)
Twitter
Open Build Service (OBS)
is an
openSUSE project
.
浙ICP备2022010568号-2