Merge
This commit is contained in:
commit
0ceb0316d6
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2005, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -32,6 +32,10 @@ import com.sun.tools.attach.spi.AttachProvider;
|
|||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.File;
|
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
|
* Linux implementation of HotSpotVirtualMachine
|
||||||
@ -63,12 +67,15 @@ public class VirtualMachineImpl extends HotSpotVirtualMachine {
|
|||||||
throw new AttachNotSupportedException("Invalid process identifier");
|
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
|
// 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.
|
// attach mechanism in the target VM by sending it a QUIT signal.
|
||||||
// Then we attempt to find the socket file again.
|
// Then we attempt to find the socket file again.
|
||||||
path = findSocketFile(pid);
|
path = findSocketFile(pid, ns_pid);
|
||||||
if (path == null) {
|
if (path == null) {
|
||||||
File f = createAttachFile(pid);
|
File f = createAttachFile(pid, ns_pid);
|
||||||
try {
|
try {
|
||||||
sendQuitTo(pid);
|
sendQuitTo(pid);
|
||||||
|
|
||||||
@ -83,7 +90,7 @@ public class VirtualMachineImpl extends HotSpotVirtualMachine {
|
|||||||
try {
|
try {
|
||||||
Thread.sleep(delay);
|
Thread.sleep(delay);
|
||||||
} catch (InterruptedException x) { }
|
} catch (InterruptedException x) { }
|
||||||
path = findSocketFile(pid);
|
path = findSocketFile(pid, ns_pid);
|
||||||
|
|
||||||
time_spend += delay;
|
time_spend += delay;
|
||||||
if (time_spend > timeout/2 && path == null) {
|
if (time_spend > timeout/2 && path == null) {
|
||||||
@ -262,8 +269,12 @@ public class VirtualMachineImpl extends HotSpotVirtualMachine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Return the socket file for the given process.
|
// Return the socket file for the given process.
|
||||||
private String findSocketFile(int pid) {
|
private String findSocketFile(int pid, int ns_pid) {
|
||||||
File f = new File(tmpdir, ".java_pid" + 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()) {
|
if (!f.exists()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -274,14 +285,23 @@ public class VirtualMachineImpl extends HotSpotVirtualMachine {
|
|||||||
// if not already started. The client creates a .attach_pid<pid> file in the
|
// 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
|
// target VM's working directory (or temp directory), and the SIGQUIT handler
|
||||||
// checks for the file.
|
// checks for the file.
|
||||||
private File createAttachFile(int pid) throws IOException {
|
private File createAttachFile(int pid, int ns_pid) throws IOException {
|
||||||
String fn = ".attach_pid" + pid;
|
String fn = ".attach_pid" + ns_pid;
|
||||||
String path = "/proc/" + pid + "/cwd/" + fn;
|
String path = "/proc/" + pid + "/cwd/" + fn;
|
||||||
File f = new File(path);
|
File f = new File(path);
|
||||||
try {
|
try {
|
||||||
f.createNewFile();
|
f.createNewFile();
|
||||||
} catch (IOException x) {
|
} 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();
|
f.createNewFile();
|
||||||
}
|
}
|
||||||
return f;
|
return f;
|
||||||
@ -307,6 +327,40 @@ public class VirtualMachineImpl 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
|
//-- native methods
|
||||||
|
|
||||||
static native void sendQuitToChildrenOf(int pid) throws IOException;
|
static native void sendQuitToChildrenOf(int pid) throws IOException;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user