27 import com.sun.tools.attach.AttachOperationFailedException;
28 import com.sun.tools.attach.AgentLoadException;
29 import com.sun.tools.attach.AttachNotSupportedException;
30 import com.sun.tools.attach.spi.AttachProvider;
31
32 import java.io.InputStream;
33 import java.io.IOException;
34 import java.io.File;
35
36 /*
37 * Linux implementation of HotSpotVirtualMachine
38 */
39 public class VirtualMachineImpl extends HotSpotVirtualMachine {
40 // "/tmp" is used as a global well-known location for the files
41 // .java_pid<pid>. and .attach_pid<pid>. It is important that this
42 // location is the same for all processes, otherwise the tools
43 // will not be able to find all Hotspot processes.
44 // Any changes to this needs to be synchronized with HotSpot.
45 private static final String tmpdir = "/tmp";
46
47 // Indicates if this machine uses the old LinuxThreads
48 static boolean isLinuxThreads;
49
50 // The patch to the socket file created by the target VM
51 String path;
52
53 /**
54 * Attaches to the target VM
55 */
56 VirtualMachineImpl(AttachProvider provider, String vmid)
57 throws AttachNotSupportedException, IOException
58 {
59 super(provider, vmid);
60
61 // This provider only understands pids
62 int pid;
63 try {
64 pid = Integer.parseInt(vmid);
65 } catch (NumberFormatException x) {
66 throw new AttachNotSupportedException("Invalid process identifier");
67 }
68
69 // Find the socket file. If not found then we attempt to start the
70 // attach mechanism in the target VM by sending it a QUIT signal.
71 // Then we attempt to find the socket file again.
72 path = findSocketFile(pid);
73 if (path == null) {
74 File f = createAttachFile(pid);
75 try {
76 // On LinuxThreads each thread is a process and we don't have the
77 // pid of the VMThread which has SIGQUIT unblocked. To workaround
78 // this we get the pid of the "manager thread" that is created
79 // by the first call to pthread_create. This is parent of all
80 // threads (except the initial thread).
81 if (isLinuxThreads) {
82 int mpid;
83 try {
84 mpid = getLinuxThreadsManager(pid);
85 } catch (IOException x) {
86 throw new AttachNotSupportedException(x.getMessage());
87 }
88 assert(mpid >= 1);
89 sendQuitToChildrenOf(mpid);
90 } else {
91 sendQuitTo(pid);
92 }
93
94 // give the target VM time to start the attach mechanism
95 int i = 0;
96 long delay = 200;
97 int retries = (int)(attachTimeout() / delay);
98 do {
99 try {
100 Thread.sleep(delay);
101 } catch (InterruptedException x) { }
102 path = findSocketFile(pid);
103 i++;
104 } while (i <= retries && path == null);
105 if (path == null) {
106 throw new AttachNotSupportedException(
107 "Unable to open socket file: target process not responding " +
108 "or HotSpot VM not loaded");
109 }
110 } finally {
111 f.delete();
112 }
113 }
114
115 // Check that the file owner/permission to avoid attaching to
116 // bogus process
117 checkPermissions(path);
118
119 // Check that we can connect to the process
120 // - this ensures we throw the permission denied error now rather than
121 // later when we attempt to enqueue a command.
122 int s = socket();
123 try {
124 connect(s, path);
125 } finally {
126 close(s);
127 }
128 }
323 static native int getLinuxThreadsManager(int pid) throws IOException;
324
325 static native void sendQuitToChildrenOf(int pid) throws IOException;
326
327 static native void sendQuitTo(int pid) throws IOException;
328
329 static native void checkPermissions(String path) throws IOException;
330
331 static native int socket() throws IOException;
332
333 static native void connect(int fd, String path) throws IOException;
334
335 static native void close(int fd) throws IOException;
336
337 static native int read(int fd, byte buf[], int off, int bufLen) throws IOException;
338
339 static native void write(int fd, byte buf[], int off, int bufLen) throws IOException;
340
341 static {
342 System.loadLibrary("attach");
343 isLinuxThreads = isLinuxThreads();
344 }
345 }
|
27 import com.sun.tools.attach.AttachOperationFailedException;
28 import com.sun.tools.attach.AgentLoadException;
29 import com.sun.tools.attach.AttachNotSupportedException;
30 import com.sun.tools.attach.spi.AttachProvider;
31
32 import java.io.InputStream;
33 import java.io.IOException;
34 import java.io.File;
35
36 /*
37 * Linux implementation of HotSpotVirtualMachine
38 */
39 public class VirtualMachineImpl extends HotSpotVirtualMachine {
40 // "/tmp" is used as a global well-known location for the files
41 // .java_pid<pid>. and .attach_pid<pid>. It is important that this
42 // location is the same for all processes, otherwise the tools
43 // will not be able to find all Hotspot processes.
44 // Any changes to this needs to be synchronized with HotSpot.
45 private static final String tmpdir = "/tmp";
46
47 // The patch to the socket file created by the target VM
48 String path;
49
50 /**
51 * Attaches to the target VM
52 */
53 VirtualMachineImpl(AttachProvider provider, String vmid)
54 throws AttachNotSupportedException, IOException
55 {
56 super(provider, vmid);
57
58 // This provider only understands pids
59 int pid;
60 try {
61 pid = Integer.parseInt(vmid);
62 } catch (NumberFormatException x) {
63 throw new AttachNotSupportedException("Invalid process identifier");
64 }
65
66 // Find the socket file. If not found then we attempt to start the
67 // attach mechanism in the target VM by sending it a QUIT signal.
68 // Then we attempt to find the socket file again.
69 path = findSocketFile(pid);
70 if (path == null) {
71 File f = createAttachFile(pid);
72 try {
73 sendQuitTo(pid);
74
75 // give the target VM time to start the attach mechanism
76 final int delay_step = 100;
77 final long timeout = attachTimeout();
78 long time_spend = 0;
79 long delay = 0;
80 do {
81 // Increase timeout on each attempt to reduce polling
82 delay += delay_step;
83 try {
84 Thread.sleep(delay);
85 } catch (InterruptedException x) { }
86 path = findSocketFile(pid);
87
88 time_spend += delay;
89 if (time_spend > timeout/2 && path == null) {
90 // Send QUIT again to give target VM the last chance to react
91 sendQuitTo(pid);
92 }
93 } while (time_spend <= timeout && path == null);
94 if (path == null) {
95 throw new AttachNotSupportedException(
96 String.format("Unable to open socket file: target process %d not responding within %dms or HotSpot VM not loaded", pid, time_spend));
97 }
98 } finally {
99 f.delete();
100 }
101 }
102
103 // Check that the file owner/permission to avoid attaching to
104 // bogus process
105 checkPermissions(path);
106
107 // Check that we can connect to the process
108 // - this ensures we throw the permission denied error now rather than
109 // later when we attempt to enqueue a command.
110 int s = socket();
111 try {
112 connect(s, path);
113 } finally {
114 close(s);
115 }
116 }
311 static native int getLinuxThreadsManager(int pid) throws IOException;
312
313 static native void sendQuitToChildrenOf(int pid) throws IOException;
314
315 static native void sendQuitTo(int pid) throws IOException;
316
317 static native void checkPermissions(String path) throws IOException;
318
319 static native int socket() throws IOException;
320
321 static native void connect(int fd, String path) throws IOException;
322
323 static native void close(int fd) throws IOException;
324
325 static native int read(int fd, byte buf[], int off, int bufLen) throws IOException;
326
327 static native void write(int fd, byte buf[], int off, int bufLen) throws IOException;
328
329 static {
330 System.loadLibrary("attach");
331 }
332 }
|