Mercurial > hg > truffle
annotate src/os/linux/vm/attachListener_linux.cpp @ 17716:cdb71841f4bc
6498581: ThreadInterruptTest3 produces wrong output on Windows
Summary: There is race condition between os::interrupt and os::is_interrupted on Windows. In JVM_Sleep(Thread.sleep), check if thread gets interrupted, it may see interrupted but not really interrupted so cause spurious waking up (early return from sleep). Fix by checking if interrupt event really gets set thus prevent false return. For intrinsic of _isInterrupted, on Windows, go fastpath only on bit not set.
Reviewed-by: acorn, kvn
Contributed-by: david.holmes@oracle.com, yumin.qi@oracle.com
author | minqi |
---|---|
date | Wed, 26 Feb 2014 15:20:41 -0800 |
parents | 2e8f19c2feef |
children |
rev | line source |
---|---|
0 | 1 /* |
11139
2e8f19c2feef
7162400: Intermittent java.io.IOException: Bad file number during HotSpotVirtualMachine.executeCommand
allwin
parents:
10978
diff
changeset
|
2 * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. |
0 | 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * | |
5 * This code is free software; you can redistribute it and/or modify it | |
6 * under the terms of the GNU General Public License version 2 only, as | |
7 * published by the Free Software Foundation. | |
8 * | |
9 * This code is distributed in the hope that it will be useful, but WITHOUT | |
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
12 * version 2 for more details (a copy is included in the LICENSE file that | |
13 * accompanied this code). | |
14 * | |
15 * You should have received a copy of the GNU General Public License version | |
16 * 2 along with this work; if not, write to the Free Software Foundation, | |
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
18 * | |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1497
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1497
diff
changeset
|
20 * or visit www.oracle.com if you need additional information or have any |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1497
diff
changeset
|
21 * questions. |
0 | 22 * |
23 */ | |
24 | |
1972 | 25 #include "precompiled.hpp" |
26 #include "runtime/interfaceSupport.hpp" | |
27 #include "runtime/os.hpp" | |
28 #include "services/attachListener.hpp" | |
29 #include "services/dtraceAttacher.hpp" | |
0 | 30 |
31 #include <unistd.h> | |
32 #include <signal.h> | |
33 #include <sys/types.h> | |
34 #include <sys/socket.h> | |
35 #include <sys/un.h> | |
36 #include <sys/stat.h> | |
37 | |
1675
a81afd9c293c
6649594: Intermittent IOExceptions during dynamic attach on linux and solaris
alanb
parents:
1552
diff
changeset
|
38 #ifndef UNIX_PATH_MAX |
a81afd9c293c
6649594: Intermittent IOExceptions during dynamic attach on linux and solaris
alanb
parents:
1552
diff
changeset
|
39 #define UNIX_PATH_MAX sizeof(((struct sockaddr_un *)0)->sun_path) |
a81afd9c293c
6649594: Intermittent IOExceptions during dynamic attach on linux and solaris
alanb
parents:
1552
diff
changeset
|
40 #endif |
a81afd9c293c
6649594: Intermittent IOExceptions during dynamic attach on linux and solaris
alanb
parents:
1552
diff
changeset
|
41 |
0 | 42 // The attach mechanism on Linux uses a UNIX domain socket. An attach listener |
43 // thread is created at startup or is created on-demand via a signal from | |
44 // the client tool. The attach listener creates a socket and binds it to a file | |
45 // in the filesystem. The attach listener then acts as a simple (single- | |
1675
a81afd9c293c
6649594: Intermittent IOExceptions during dynamic attach on linux and solaris
alanb
parents:
1552
diff
changeset
|
46 // threaded) server - it waits for a client to connect, reads the request, |
0 | 47 // executes it, and returns the response to the client via the socket |
48 // connection. | |
49 // | |
50 // As the socket is a UNIX domain socket it means that only clients on the | |
51 // local machine can connect. In addition there are two other aspects to | |
52 // the security: | |
53 // 1. The well known file that the socket is bound to has permission 400 | |
54 // 2. When a client connect, the SO_PEERCRED socket option is used to | |
55 // obtain the credentials of client. We check that the effective uid | |
56 // of the client matches this process. | |
57 | |
58 // forward reference | |
59 class LinuxAttachOperation; | |
60 | |
61 class LinuxAttachListener: AllStatic { | |
62 private: | |
63 // the path to which we bind the UNIX domain socket | |
1675
a81afd9c293c
6649594: Intermittent IOExceptions during dynamic attach on linux and solaris
alanb
parents:
1552
diff
changeset
|
64 static char _path[UNIX_PATH_MAX]; |
0 | 65 static bool _has_path; |
66 | |
67 // the file descriptor for the listening socket | |
68 static int _listener; | |
69 | |
70 static void set_path(char* path) { | |
71 if (path == NULL) { | |
72 _has_path = false; | |
73 } else { | |
1675
a81afd9c293c
6649594: Intermittent IOExceptions during dynamic attach on linux and solaris
alanb
parents:
1552
diff
changeset
|
74 strncpy(_path, path, UNIX_PATH_MAX); |
a81afd9c293c
6649594: Intermittent IOExceptions during dynamic attach on linux and solaris
alanb
parents:
1552
diff
changeset
|
75 _path[UNIX_PATH_MAX-1] = '\0'; |
0 | 76 _has_path = true; |
77 } | |
78 } | |
79 | |
80 static void set_listener(int s) { _listener = s; } | |
81 | |
82 // reads a request from the given connected socket | |
83 static LinuxAttachOperation* read_request(int s); | |
84 | |
85 public: | |
86 enum { | |
87 ATTACH_PROTOCOL_VER = 1 // protocol version | |
88 }; | |
89 enum { | |
90 ATTACH_ERROR_BADVERSION = 101 // error codes | |
91 }; | |
92 | |
93 // initialize the listener, returns 0 if okay | |
94 static int init(); | |
95 | |
96 static char* path() { return _path; } | |
97 static bool has_path() { return _has_path; } | |
98 static int listener() { return _listener; } | |
99 | |
100 // write the given buffer to a socket | |
101 static int write_fully(int s, char* buf, int len); | |
102 | |
103 static LinuxAttachOperation* dequeue(); | |
104 }; | |
105 | |
106 class LinuxAttachOperation: public AttachOperation { | |
107 private: | |
108 // the connection to the client | |
109 int _socket; | |
110 | |
111 public: | |
112 void complete(jint res, bufferedStream* st); | |
113 | |
114 void set_socket(int s) { _socket = s; } | |
115 int socket() const { return _socket; } | |
116 | |
117 LinuxAttachOperation(char* name) : AttachOperation(name) { | |
118 set_socket(-1); | |
119 } | |
120 }; | |
121 | |
122 // statics | |
1675
a81afd9c293c
6649594: Intermittent IOExceptions during dynamic attach on linux and solaris
alanb
parents:
1552
diff
changeset
|
123 char LinuxAttachListener::_path[UNIX_PATH_MAX]; |
0 | 124 bool LinuxAttachListener::_has_path; |
125 int LinuxAttachListener::_listener = -1; | |
126 | |
127 // Supporting class to help split a buffer into individual components | |
128 class ArgumentIterator : public StackObj { | |
129 private: | |
130 char* _pos; | |
131 char* _end; | |
132 public: | |
133 ArgumentIterator(char* arg_buffer, size_t arg_size) { | |
134 _pos = arg_buffer; | |
135 _end = _pos + arg_size - 1; | |
136 } | |
137 char* next() { | |
138 if (*_pos == '\0') { | |
139 return NULL; | |
140 } | |
141 char* res = _pos; | |
142 char* next_pos = strchr(_pos, '\0'); | |
143 if (next_pos < _end) { | |
144 next_pos++; | |
145 } | |
146 _pos = next_pos; | |
147 return res; | |
148 } | |
149 }; | |
150 | |
151 | |
152 // atexit hook to stop listener and unlink the file that it is | |
153 // bound too. | |
154 extern "C" { | |
155 static void listener_cleanup() { | |
156 static int cleanup_done; | |
157 if (!cleanup_done) { | |
158 cleanup_done = 1; | |
159 int s = LinuxAttachListener::listener(); | |
160 if (s != -1) { | |
161 ::close(s); | |
162 } | |
163 if (LinuxAttachListener::has_path()) { | |
164 ::unlink(LinuxAttachListener::path()); | |
165 } | |
166 } | |
167 } | |
168 } | |
169 | |
170 // Initialization - create a listener socket and bind it to a file | |
171 | |
172 int LinuxAttachListener::init() { | |
1675
a81afd9c293c
6649594: Intermittent IOExceptions during dynamic attach on linux and solaris
alanb
parents:
1552
diff
changeset
|
173 char path[UNIX_PATH_MAX]; // socket file |
a81afd9c293c
6649594: Intermittent IOExceptions during dynamic attach on linux and solaris
alanb
parents:
1552
diff
changeset
|
174 char initial_path[UNIX_PATH_MAX]; // socket file during setup |
a81afd9c293c
6649594: Intermittent IOExceptions during dynamic attach on linux and solaris
alanb
parents:
1552
diff
changeset
|
175 int listener; // listener socket (file descriptor) |
0 | 176 |
177 // register function to cleanup | |
178 ::atexit(listener_cleanup); | |
179 | |
1675
a81afd9c293c
6649594: Intermittent IOExceptions during dynamic attach on linux and solaris
alanb
parents:
1552
diff
changeset
|
180 int n = snprintf(path, UNIX_PATH_MAX, "%s/.java_pid%d", |
a81afd9c293c
6649594: Intermittent IOExceptions during dynamic attach on linux and solaris
alanb
parents:
1552
diff
changeset
|
181 os::get_temp_directory(), os::current_process_id()); |
1868
3dc12ef8735e
6989297: Integrate additional portability improvements
bobv
parents:
1675
diff
changeset
|
182 if (n < (int)UNIX_PATH_MAX) { |
1675
a81afd9c293c
6649594: Intermittent IOExceptions during dynamic attach on linux and solaris
alanb
parents:
1552
diff
changeset
|
183 n = snprintf(initial_path, UNIX_PATH_MAX, "%s.tmp", path); |
a81afd9c293c
6649594: Intermittent IOExceptions during dynamic attach on linux and solaris
alanb
parents:
1552
diff
changeset
|
184 } |
1868
3dc12ef8735e
6989297: Integrate additional portability improvements
bobv
parents:
1675
diff
changeset
|
185 if (n >= (int)UNIX_PATH_MAX) { |
1675
a81afd9c293c
6649594: Intermittent IOExceptions during dynamic attach on linux and solaris
alanb
parents:
1552
diff
changeset
|
186 return -1; |
a81afd9c293c
6649594: Intermittent IOExceptions during dynamic attach on linux and solaris
alanb
parents:
1552
diff
changeset
|
187 } |
a81afd9c293c
6649594: Intermittent IOExceptions during dynamic attach on linux and solaris
alanb
parents:
1552
diff
changeset
|
188 |
0 | 189 // create the listener socket |
190 listener = ::socket(PF_UNIX, SOCK_STREAM, 0); | |
191 if (listener == -1) { | |
192 return -1; | |
193 } | |
194 | |
1675
a81afd9c293c
6649594: Intermittent IOExceptions during dynamic attach on linux and solaris
alanb
parents:
1552
diff
changeset
|
195 // bind socket |
0 | 196 struct sockaddr_un addr; |
197 addr.sun_family = AF_UNIX; | |
1675
a81afd9c293c
6649594: Intermittent IOExceptions during dynamic attach on linux and solaris
alanb
parents:
1552
diff
changeset
|
198 strcpy(addr.sun_path, initial_path); |
a81afd9c293c
6649594: Intermittent IOExceptions during dynamic attach on linux and solaris
alanb
parents:
1552
diff
changeset
|
199 ::unlink(initial_path); |
a81afd9c293c
6649594: Intermittent IOExceptions during dynamic attach on linux and solaris
alanb
parents:
1552
diff
changeset
|
200 int res = ::bind(listener, (struct sockaddr*)&addr, sizeof(addr)); |
0 | 201 if (res == -1) { |
10978
e95fc50106cf
7178026: os::close can restart ::close but that is not a restartable syscall
rdurbin
parents:
1972
diff
changeset
|
202 ::close(listener); |
0 | 203 return -1; |
204 } | |
205 | |
1675
a81afd9c293c
6649594: Intermittent IOExceptions during dynamic attach on linux and solaris
alanb
parents:
1552
diff
changeset
|
206 // put in listen mode, set permissions, and rename into place |
a81afd9c293c
6649594: Intermittent IOExceptions during dynamic attach on linux and solaris
alanb
parents:
1552
diff
changeset
|
207 res = ::listen(listener, 5); |
a81afd9c293c
6649594: Intermittent IOExceptions during dynamic attach on linux and solaris
alanb
parents:
1552
diff
changeset
|
208 if (res == 0) { |
a81afd9c293c
6649594: Intermittent IOExceptions during dynamic attach on linux and solaris
alanb
parents:
1552
diff
changeset
|
209 RESTARTABLE(::chmod(initial_path, S_IREAD|S_IWRITE), res); |
a81afd9c293c
6649594: Intermittent IOExceptions during dynamic attach on linux and solaris
alanb
parents:
1552
diff
changeset
|
210 if (res == 0) { |
a81afd9c293c
6649594: Intermittent IOExceptions during dynamic attach on linux and solaris
alanb
parents:
1552
diff
changeset
|
211 res = ::rename(initial_path, path); |
a81afd9c293c
6649594: Intermittent IOExceptions during dynamic attach on linux and solaris
alanb
parents:
1552
diff
changeset
|
212 } |
a81afd9c293c
6649594: Intermittent IOExceptions during dynamic attach on linux and solaris
alanb
parents:
1552
diff
changeset
|
213 } |
a81afd9c293c
6649594: Intermittent IOExceptions during dynamic attach on linux and solaris
alanb
parents:
1552
diff
changeset
|
214 if (res == -1) { |
10978
e95fc50106cf
7178026: os::close can restart ::close but that is not a restartable syscall
rdurbin
parents:
1972
diff
changeset
|
215 ::close(listener); |
1675
a81afd9c293c
6649594: Intermittent IOExceptions during dynamic attach on linux and solaris
alanb
parents:
1552
diff
changeset
|
216 ::unlink(initial_path); |
0 | 217 return -1; |
218 } | |
1675
a81afd9c293c
6649594: Intermittent IOExceptions during dynamic attach on linux and solaris
alanb
parents:
1552
diff
changeset
|
219 set_path(path); |
0 | 220 set_listener(listener); |
221 | |
222 return 0; | |
223 } | |
224 | |
225 // Given a socket that is connected to a peer we read the request and | |
226 // create an AttachOperation. As the socket is blocking there is potential | |
227 // for a denial-of-service if the peer does not response. However this happens | |
228 // after the peer credentials have been checked and in the worst case it just | |
229 // means that the attach listener thread is blocked. | |
230 // | |
231 LinuxAttachOperation* LinuxAttachListener::read_request(int s) { | |
232 char ver_str[8]; | |
233 sprintf(ver_str, "%d", ATTACH_PROTOCOL_VER); | |
234 | |
235 // The request is a sequence of strings so we first figure out the | |
236 // expected count and the maximum possible length of the request. | |
237 // The request is: | |
238 // <ver>0<cmd>0<arg>0<arg>0<arg>0 | |
239 // where <ver> is the protocol version (1), <cmd> is the command | |
240 // name ("load", "datadump", ...), and <arg> is an argument | |
241 int expected_str_count = 2 + AttachOperation::arg_count_max; | |
50
485d403e94e1
6452081: 3/4 Allow for Linux builds with Sun Studio Linux compilers
dcubed
parents:
0
diff
changeset
|
242 const int max_len = (sizeof(ver_str) + 1) + (AttachOperation::name_length_max + 1) + |
0 | 243 AttachOperation::arg_count_max*(AttachOperation::arg_length_max + 1); |
244 | |
245 char buf[max_len]; | |
246 int str_count = 0; | |
247 | |
248 // Read until all (expected) strings have been read, the buffer is | |
249 // full, or EOF. | |
250 | |
251 int off = 0; | |
252 int left = max_len; | |
253 | |
254 do { | |
255 int n; | |
256 RESTARTABLE(read(s, buf+off, left), n); | |
257 if (n == -1) { | |
258 return NULL; // reset by peer or other error | |
259 } | |
260 if (n == 0) { | |
261 break; | |
262 } | |
263 for (int i=0; i<n; i++) { | |
264 if (buf[off+i] == 0) { | |
265 // EOS found | |
266 str_count++; | |
267 | |
268 // The first string is <ver> so check it now to | |
269 // check for protocol mis-match | |
270 if (str_count == 1) { | |
271 if ((strlen(buf) != strlen(ver_str)) || | |
272 (atoi(buf) != ATTACH_PROTOCOL_VER)) { | |
273 char msg[32]; | |
274 sprintf(msg, "%d\n", ATTACH_ERROR_BADVERSION); | |
275 write_fully(s, msg, strlen(msg)); | |
276 return NULL; | |
277 } | |
278 } | |
279 } | |
280 } | |
281 off += n; | |
282 left -= n; | |
283 } while (left > 0 && str_count < expected_str_count); | |
284 | |
285 if (str_count != expected_str_count) { | |
286 return NULL; // incomplete request | |
287 } | |
288 | |
289 // parse request | |
290 | |
291 ArgumentIterator args(buf, (max_len)-left); | |
292 | |
293 // version already checked | |
294 char* v = args.next(); | |
295 | |
296 char* name = args.next(); | |
297 if (name == NULL || strlen(name) > AttachOperation::name_length_max) { | |
298 return NULL; | |
299 } | |
300 | |
301 LinuxAttachOperation* op = new LinuxAttachOperation(name); | |
302 | |
303 for (int i=0; i<AttachOperation::arg_count_max; i++) { | |
304 char* arg = args.next(); | |
305 if (arg == NULL) { | |
306 op->set_arg(i, NULL); | |
307 } else { | |
308 if (strlen(arg) > AttachOperation::arg_length_max) { | |
309 delete op; | |
310 return NULL; | |
311 } | |
312 op->set_arg(i, arg); | |
313 } | |
314 } | |
315 | |
316 op->set_socket(s); | |
317 return op; | |
318 } | |
319 | |
320 | |
321 // Dequeue an operation | |
322 // | |
323 // In the Linux implementation there is only a single operation and clients | |
324 // cannot queue commands (except at the socket level). | |
325 // | |
326 LinuxAttachOperation* LinuxAttachListener::dequeue() { | |
327 for (;;) { | |
328 int s; | |
329 | |
330 // wait for client to connect | |
331 struct sockaddr addr; | |
332 socklen_t len = sizeof(addr); | |
333 RESTARTABLE(::accept(listener(), &addr, &len), s); | |
334 if (s == -1) { | |
335 return NULL; // log a warning? | |
336 } | |
337 | |
338 // get the credentials of the peer and check the effective uid/guid | |
339 // - check with jeff on this. | |
340 struct ucred cred_info; | |
341 socklen_t optlen = sizeof(cred_info); | |
342 if (::getsockopt(s, SOL_SOCKET, SO_PEERCRED, (void*)&cred_info, &optlen) == -1) { | |
10978
e95fc50106cf
7178026: os::close can restart ::close but that is not a restartable syscall
rdurbin
parents:
1972
diff
changeset
|
343 ::close(s); |
0 | 344 continue; |
345 } | |
346 uid_t euid = geteuid(); | |
347 gid_t egid = getegid(); | |
348 | |
349 if (cred_info.uid != euid || cred_info.gid != egid) { | |
10978
e95fc50106cf
7178026: os::close can restart ::close but that is not a restartable syscall
rdurbin
parents:
1972
diff
changeset
|
350 ::close(s); |
0 | 351 continue; |
352 } | |
353 | |
354 // peer credential look okay so we read the request | |
355 LinuxAttachOperation* op = read_request(s); | |
356 if (op == NULL) { | |
10978
e95fc50106cf
7178026: os::close can restart ::close but that is not a restartable syscall
rdurbin
parents:
1972
diff
changeset
|
357 ::close(s); |
0 | 358 continue; |
359 } else { | |
360 return op; | |
361 } | |
362 } | |
363 } | |
364 | |
365 // write the given buffer to the socket | |
366 int LinuxAttachListener::write_fully(int s, char* buf, int len) { | |
367 do { | |
368 int n = ::write(s, buf, len); | |
369 if (n == -1) { | |
370 if (errno != EINTR) return -1; | |
371 } else { | |
372 buf += n; | |
373 len -= n; | |
374 } | |
375 } | |
376 while (len > 0); | |
377 return 0; | |
378 } | |
379 | |
380 // Complete an operation by sending the operation result and any result | |
381 // output to the client. At this time the socket is in blocking mode so | |
382 // potentially we can block if there is a lot of data and the client is | |
383 // non-responsive. For most operations this is a non-issue because the | |
384 // default send buffer is sufficient to buffer everything. In the future | |
385 // if there are operations that involves a very big reply then it the | |
386 // socket could be made non-blocking and a timeout could be used. | |
387 | |
388 void LinuxAttachOperation::complete(jint result, bufferedStream* st) { | |
389 JavaThread* thread = JavaThread::current(); | |
390 ThreadBlockInVM tbivm(thread); | |
391 | |
392 thread->set_suspend_equivalent(); | |
393 // cleared by handle_special_suspend_equivalent_condition() or | |
394 // java_suspend_self() via check_and_wait_while_suspended() | |
395 | |
396 // write operation result | |
397 char msg[32]; | |
398 sprintf(msg, "%d\n", result); | |
399 int rc = LinuxAttachListener::write_fully(this->socket(), msg, strlen(msg)); | |
400 | |
401 // write any result data | |
402 if (rc == 0) { | |
403 LinuxAttachListener::write_fully(this->socket(), (char*) st->base(), st->size()); | |
404 ::shutdown(this->socket(), 2); | |
405 } | |
406 | |
407 // done | |
10978
e95fc50106cf
7178026: os::close can restart ::close but that is not a restartable syscall
rdurbin
parents:
1972
diff
changeset
|
408 ::close(this->socket()); |
0 | 409 |
410 // were we externally suspended while we were waiting? | |
411 thread->check_and_wait_while_suspended(); | |
412 | |
413 delete this; | |
414 } | |
415 | |
416 | |
417 // AttachListener functions | |
418 | |
419 AttachOperation* AttachListener::dequeue() { | |
420 JavaThread* thread = JavaThread::current(); | |
421 ThreadBlockInVM tbivm(thread); | |
422 | |
423 thread->set_suspend_equivalent(); | |
424 // cleared by handle_special_suspend_equivalent_condition() or | |
425 // java_suspend_self() via check_and_wait_while_suspended() | |
426 | |
427 AttachOperation* op = LinuxAttachListener::dequeue(); | |
428 | |
429 // were we externally suspended while we were waiting? | |
430 thread->check_and_wait_while_suspended(); | |
431 | |
432 return op; | |
433 } | |
434 | |
11139
2e8f19c2feef
7162400: Intermittent java.io.IOException: Bad file number during HotSpotVirtualMachine.executeCommand
allwin
parents:
10978
diff
changeset
|
435 |
2e8f19c2feef
7162400: Intermittent java.io.IOException: Bad file number during HotSpotVirtualMachine.executeCommand
allwin
parents:
10978
diff
changeset
|
436 // Performs initialization at vm startup |
2e8f19c2feef
7162400: Intermittent java.io.IOException: Bad file number during HotSpotVirtualMachine.executeCommand
allwin
parents:
10978
diff
changeset
|
437 // For Linux we remove any stale .java_pid file which could cause |
2e8f19c2feef
7162400: Intermittent java.io.IOException: Bad file number during HotSpotVirtualMachine.executeCommand
allwin
parents:
10978
diff
changeset
|
438 // an attaching process to think we are ready to receive on the |
2e8f19c2feef
7162400: Intermittent java.io.IOException: Bad file number during HotSpotVirtualMachine.executeCommand
allwin
parents:
10978
diff
changeset
|
439 // domain socket before we are properly initialized |
2e8f19c2feef
7162400: Intermittent java.io.IOException: Bad file number during HotSpotVirtualMachine.executeCommand
allwin
parents:
10978
diff
changeset
|
440 |
2e8f19c2feef
7162400: Intermittent java.io.IOException: Bad file number during HotSpotVirtualMachine.executeCommand
allwin
parents:
10978
diff
changeset
|
441 void AttachListener::vm_start() { |
2e8f19c2feef
7162400: Intermittent java.io.IOException: Bad file number during HotSpotVirtualMachine.executeCommand
allwin
parents:
10978
diff
changeset
|
442 char fn[UNIX_PATH_MAX]; |
2e8f19c2feef
7162400: Intermittent java.io.IOException: Bad file number during HotSpotVirtualMachine.executeCommand
allwin
parents:
10978
diff
changeset
|
443 struct stat64 st; |
2e8f19c2feef
7162400: Intermittent java.io.IOException: Bad file number during HotSpotVirtualMachine.executeCommand
allwin
parents:
10978
diff
changeset
|
444 int ret; |
2e8f19c2feef
7162400: Intermittent java.io.IOException: Bad file number during HotSpotVirtualMachine.executeCommand
allwin
parents:
10978
diff
changeset
|
445 |
2e8f19c2feef
7162400: Intermittent java.io.IOException: Bad file number during HotSpotVirtualMachine.executeCommand
allwin
parents:
10978
diff
changeset
|
446 int n = snprintf(fn, UNIX_PATH_MAX, "%s/.java_pid%d", |
2e8f19c2feef
7162400: Intermittent java.io.IOException: Bad file number during HotSpotVirtualMachine.executeCommand
allwin
parents:
10978
diff
changeset
|
447 os::get_temp_directory(), os::current_process_id()); |
2e8f19c2feef
7162400: Intermittent java.io.IOException: Bad file number during HotSpotVirtualMachine.executeCommand
allwin
parents:
10978
diff
changeset
|
448 assert(n < (int)UNIX_PATH_MAX, "java_pid file name buffer overflow"); |
2e8f19c2feef
7162400: Intermittent java.io.IOException: Bad file number during HotSpotVirtualMachine.executeCommand
allwin
parents:
10978
diff
changeset
|
449 |
2e8f19c2feef
7162400: Intermittent java.io.IOException: Bad file number during HotSpotVirtualMachine.executeCommand
allwin
parents:
10978
diff
changeset
|
450 RESTARTABLE(::stat64(fn, &st), ret); |
2e8f19c2feef
7162400: Intermittent java.io.IOException: Bad file number during HotSpotVirtualMachine.executeCommand
allwin
parents:
10978
diff
changeset
|
451 if (ret == 0) { |
2e8f19c2feef
7162400: Intermittent java.io.IOException: Bad file number during HotSpotVirtualMachine.executeCommand
allwin
parents:
10978
diff
changeset
|
452 ret = ::unlink(fn); |
2e8f19c2feef
7162400: Intermittent java.io.IOException: Bad file number during HotSpotVirtualMachine.executeCommand
allwin
parents:
10978
diff
changeset
|
453 if (ret == -1) { |
2e8f19c2feef
7162400: Intermittent java.io.IOException: Bad file number during HotSpotVirtualMachine.executeCommand
allwin
parents:
10978
diff
changeset
|
454 debug_only(warning("failed to remove stale attach pid file at %s", fn)); |
2e8f19c2feef
7162400: Intermittent java.io.IOException: Bad file number during HotSpotVirtualMachine.executeCommand
allwin
parents:
10978
diff
changeset
|
455 } |
2e8f19c2feef
7162400: Intermittent java.io.IOException: Bad file number during HotSpotVirtualMachine.executeCommand
allwin
parents:
10978
diff
changeset
|
456 } |
2e8f19c2feef
7162400: Intermittent java.io.IOException: Bad file number during HotSpotVirtualMachine.executeCommand
allwin
parents:
10978
diff
changeset
|
457 } |
2e8f19c2feef
7162400: Intermittent java.io.IOException: Bad file number during HotSpotVirtualMachine.executeCommand
allwin
parents:
10978
diff
changeset
|
458 |
0 | 459 int AttachListener::pd_init() { |
460 JavaThread* thread = JavaThread::current(); | |
461 ThreadBlockInVM tbivm(thread); | |
462 | |
463 thread->set_suspend_equivalent(); | |
464 // cleared by handle_special_suspend_equivalent_condition() or | |
465 // java_suspend_self() via check_and_wait_while_suspended() | |
466 | |
467 int ret_code = LinuxAttachListener::init(); | |
468 | |
469 // were we externally suspended while we were waiting? | |
470 thread->check_and_wait_while_suspended(); | |
471 | |
472 return ret_code; | |
473 } | |
474 | |
475 // Attach Listener is started lazily except in the case when | |
476 // +ReduseSignalUsage is used | |
477 bool AttachListener::init_at_startup() { | |
478 if (ReduceSignalUsage) { | |
479 return true; | |
480 } else { | |
481 return false; | |
482 } | |
483 } | |
484 | |
485 // If the file .attach_pid<pid> exists in the working directory | |
486 // or /tmp then this is the trigger to start the attach mechanism | |
487 bool AttachListener::is_init_trigger() { | |
488 if (init_at_startup() || is_initialized()) { | |
489 return false; // initialized at startup or already initialized | |
490 } | |
1497
96d554193f72
6944822: Fix for 6938627 exposes problem with hard-coded buffer sizes
coleenp
parents:
1353
diff
changeset
|
491 char fn[PATH_MAX+1]; |
0 | 492 sprintf(fn, ".attach_pid%d", os::current_process_id()); |
493 int ret; | |
494 struct stat64 st; | |
495 RESTARTABLE(::stat64(fn, &st), ret); | |
496 if (ret == -1) { | |
1353
a2ea687fdc7c
6938627: Make temporary directory use property java.io.tmpdir when specified
coleenp
parents:
196
diff
changeset
|
497 snprintf(fn, sizeof(fn), "%s/.attach_pid%d", |
a2ea687fdc7c
6938627: Make temporary directory use property java.io.tmpdir when specified
coleenp
parents:
196
diff
changeset
|
498 os::get_temp_directory(), os::current_process_id()); |
0 | 499 RESTARTABLE(::stat64(fn, &st), ret); |
500 } | |
501 if (ret == 0) { | |
502 // simple check to avoid starting the attach mechanism when | |
503 // a bogus user creates the file | |
504 if (st.st_uid == geteuid()) { | |
505 init(); | |
506 return true; | |
507 } | |
508 } | |
509 return false; | |
510 } | |
511 | |
512 // if VM aborts then remove listener | |
513 void AttachListener::abort() { | |
514 listener_cleanup(); | |
515 } | |
516 | |
517 void AttachListener::pd_data_dump() { | |
518 os::signal_notify(SIGQUIT); | |
519 } | |
520 | |
521 AttachOperationFunctionInfo* AttachListener::pd_find_operation(const char* n) { | |
522 return NULL; | |
523 } | |
524 | |
525 jint AttachListener::pd_set_flag(AttachOperation* op, outputStream* out) { | |
526 out->print_cr("flag '%s' cannot be changed", op->arg(0)); | |
527 return JNI_ERR; | |
528 } | |
529 | |
530 void AttachListener::pd_detachall() { | |
531 // do nothing for now | |
532 } |