1 /*
2 * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
3 * Copyright (c) 2015 SAP SE. All rights reserved.
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 *
6 * This code is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License version 2 only, as
8 * published by the Free Software Foundation. Oracle designates this
9 * particular file as subject to the "Classpath" exception as provided
10 * by Oracle in the LICENSE file that accompanied this code.
11 *
12 * This code is distributed in the hope that it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 * version 2 for more details (a copy is included in the LICENSE file that
16 * accompanied this code).
17 *
18 * You should have received a copy of the GNU General Public License version
19 * 2 along with this work; if not, write to the Free Software Foundation,
20 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
21 *
22 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
29 import com.sun.tools.attach.AgentLoadException;
30 import com.sun.tools.attach.AttachNotSupportedException;
31 import com.sun.tools.attach.spi.AttachProvider;
32
33 import java.io.InputStream;
34 import java.io.IOException;
35 import java.io.File;
36
37 // Based on linux/classes/sun/tools/attach/VirtualMachineImpl.java.
38
39 /*
40 * Aix implementation of HotSpotVirtualMachine
41 */
42 public class VirtualMachineImpl extends HotSpotVirtualMachine {
43 // "/tmp" is used as a global well-known location for the files
44 // .java_pid<pid>. and .attach_pid<pid>. It is important that this
45 // location is the same for all processes, otherwise the tools
46 // will not be able to find all Hotspot processes.
47 // Any changes to this needs to be synchronized with HotSpot.
48 private static final String tmpdir = "/tmp";
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 sendQuitTo(pid);
77
78 // give the target VM time to start the attach mechanism
79 final int delay_step = 100;
80 final long timeout = attachTimeout();
81 long time_spend = 0;
82 long delay = 0;
83 do {
84 // Increase timeout on each attempt to reduce polling
85 delay += delay_step;
86 try {
87 Thread.sleep(delay);
88 } catch (InterruptedException x) { }
89 path = findSocketFile(pid);
90
91 time_spend += delay;
92 if (time_spend > timeout/2 && path == null) {
93 // Send QUIT again to give target VM the last chance to react
94 sendQuitTo(pid);
95 }
96 } while (time_spend <= timeout && path == null);
97 if (path == null) {
98 throw new AttachNotSupportedException(
99 String.format("Unable to open socket file %s: " +
100 "target process %d doesn't respond within %dms " +
101 "or HotSpot VM not loaded", f.getPath(), pid, time_spend));
102 }
103 } finally {
104 f.delete();
105 }
106 }
107
108 // Check that the file owner/permission to avoid attaching to
109 // bogus process
110 checkPermissions(path);
111
112 // Check that we can connect to the process
113 // - this ensures we throw the permission denied error now rather than
114 // later when we attempt to enqueue a command.
115 int s = socket();
116 try {
117 connect(s, path);
118 } finally {
119 close(s);
120 }
121 }
122
123 /**
124 * Detach from the target VM
125 */
126 public void detach() throws IOException {
127 synchronized (this) {
128 if (this.path != null) {
129 this.path = null;
130 }
131 }
132 }
133
134 // protocol version
135 private final static String PROTOCOL_VERSION = "1";
136
137 // known errors
245 if (n == 1) {
246 return b[0] & 0xff;
247 } else {
248 return -1;
249 }
250 }
251
252 public synchronized int read(byte[] bs, int off, int len) throws IOException {
253 if ((off < 0) || (off > bs.length) || (len < 0) ||
254 ((off + len) > bs.length) || ((off + len) < 0)) {
255 throw new IndexOutOfBoundsException();
256 } else if (len == 0)
257 return 0;
258
259 return VirtualMachineImpl.read(s, bs, off, len);
260 }
261
262 public void close() throws IOException {
263 VirtualMachineImpl.close(s);
264 }
265 }
266
267 // Return the socket file for the given process.
268 private String findSocketFile(int pid) {
269 File f = new File(tmpdir, ".java_pid" + pid);
270 if (!f.exists()) {
271 return null;
272 }
273 return f.getPath();
274 }
275
276 // On Solaris/Linux/Aix a simple handshake is used to start the attach mechanism
277 // if not already started. The client creates a .attach_pid<pid> file in the
278 // target VM's working directory (or temp directory), and the SIGQUIT handler
279 // checks for the file.
280 private File createAttachFile(int pid) throws IOException {
281 String fn = ".attach_pid" + pid;
282 String path = "/proc/" + pid + "/cwd/" + fn;
283 File f = new File(path);
284 try {
285 f.createNewFile();
286 } catch (IOException x) {
287 f = new File(tmpdir, fn);
288 f.createNewFile();
289 }
290 return f;
291 }
292
293 /*
|
1 /*
2 * Copyright (c) 2008, 2017, Oracle and/or its affiliates. All rights reserved.
3 * Copyright (c) 2015 SAP SE. All rights reserved.
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 *
6 * This code is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License version 2 only, as
8 * published by the Free Software Foundation. Oracle designates this
9 * particular file as subject to the "Classpath" exception as provided
10 * by Oracle in the LICENSE file that accompanied this code.
11 *
12 * This code is distributed in the hope that it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 * version 2 for more details (a copy is included in the LICENSE file that
16 * accompanied this code).
17 *
18 * You should have received a copy of the GNU General Public License version
19 * 2 along with this work; if not, write to the Free Software Foundation,
20 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
21 *
22 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
29 import com.sun.tools.attach.AgentLoadException;
30 import com.sun.tools.attach.AttachNotSupportedException;
31 import com.sun.tools.attach.spi.AttachProvider;
32
33 import java.io.InputStream;
34 import java.io.IOException;
35 import java.io.File;
36
37 // Based on linux/classes/sun/tools/attach/VirtualMachineImpl.java.
38
39 /*
40 * Aix implementation of HotSpotVirtualMachine
41 */
42 public class VirtualMachineImpl extends HotSpotVirtualMachine {
43 // "/tmp" is used as a global well-known location for the files
44 // .java_pid<pid>. and .attach_pid<pid>. It is important that this
45 // location is the same for all processes, otherwise the tools
46 // will not be able to find all Hotspot processes.
47 // Any changes to this needs to be synchronized with HotSpot.
48 private static final String tmpdir = "/tmp";
49 String socket_name;
50
51 /**
52 * Attaches to the target VM
53 */
54 VirtualMachineImpl(AttachProvider provider, String vmid)
55 throws AttachNotSupportedException, IOException
56 {
57 super(provider, vmid);
58
59 // This provider only understands pids
60 int pid;
61 try {
62 pid = Integer.parseInt(vmid);
63 } catch (NumberFormatException x) {
64 throw new AttachNotSupportedException("Invalid process identifier");
65 }
66
67 // Find the socket file. If not found then we attempt to start the
68 // attach mechanism in the target VM by sending it a QUIT signal.
69 // Then we attempt to find the socket file again.
70 File path = new File(tmpdir, ".java_pid" + pid);
71 socket_name = path.getPath();
72 if (!path.exists()) {
73 File f = createAttachFile(pid);
74 try {
75 sendQuitTo(pid);
76
77 // give the target VM time to start the attach mechanism
78 final int delay_step = 100;
79 final long timeout = attachTimeout();
80 long time_spend = 0;
81 long delay = 0;
82 do {
83 // Increase timeout on each attempt to reduce polling
84 delay += delay_step;
85 try {
86 Thread.sleep(delay);
87 } catch (InterruptedException x) { }
88
89 time_spend += delay;
90 if (time_spend > timeout/2 && !path.exists()) {
91 // Send QUIT again to give target VM the last chance to react
92 sendQuitTo(pid);
93 }
94 } while (time_spend <= timeout && !path.exists());
95 if (!path.exists()) {
96 throw new AttachNotSupportedException(
97 String.format("Unable to open socket file %s: " +
98 "target process %d doesn't respond within %dms " +
99 "or HotSpot VM not loaded", socket_name, pid,
100 time_spend));
101 }
102 } finally {
103 f.delete();
104 }
105 }
106
107 // Check that the file owner/permission to avoid attaching to
108 // bogus process
109 checkPermissions(socket_name);
110
111 // Check that we can connect to the process
112 // - this ensures we throw the permission denied error now rather than
113 // later when we attempt to enqueue a command.
114 int s = socket();
115 try {
116 connect(s, socket_name);
117 } finally {
118 close(s);
119 }
120 }
121
122 /**
123 * Detach from the target VM
124 */
125 public void detach() throws IOException {
126 synchronized (this) {
127 if (this.path != null) {
128 this.path = null;
129 }
130 }
131 }
132
133 // protocol version
134 private final static String PROTOCOL_VERSION = "1";
135
136 // known errors
244 if (n == 1) {
245 return b[0] & 0xff;
246 } else {
247 return -1;
248 }
249 }
250
251 public synchronized int read(byte[] bs, int off, int len) throws IOException {
252 if ((off < 0) || (off > bs.length) || (len < 0) ||
253 ((off + len) > bs.length) || ((off + len) < 0)) {
254 throw new IndexOutOfBoundsException();
255 } else if (len == 0)
256 return 0;
257
258 return VirtualMachineImpl.read(s, bs, off, len);
259 }
260
261 public void close() throws IOException {
262 VirtualMachineImpl.close(s);
263 }
264 }
265
266 // On Solaris/Linux/Aix a simple handshake is used to start the attach mechanism
267 // if not already started. The client creates a .attach_pid<pid> file in the
268 // target VM's working directory (or temp directory), and the SIGQUIT handler
269 // checks for the file.
270 private File createAttachFile(int pid) throws IOException {
271 String fn = ".attach_pid" + pid;
272 String path = "/proc/" + pid + "/cwd/" + fn;
273 File f = new File(path);
274 try {
275 f.createNewFile();
276 } catch (IOException x) {
277 f = new File(tmpdir, fn);
278 f.createNewFile();
279 }
280 return f;
281 }
282
283 /*
|