Mercurial > hg > truffle
annotate src/os/windows/vm/attachListener_windows.cpp @ 20338:8d5f66b42c53
8055525: Bigapp weblogic+medrec fails to startup after JDK-8038423
Summary: If large pages are enabled and configured in Linux, the VM always pre-commits the entire space. The VM fails verification of the commit of the initial heap because some internal data structure marked all memory pages of the heap as committed during initialization. This makes the code think that we attempted a double-commit during first allocation of the heap. Remove the initial marking of memory pages of the heap to committed.
Reviewed-by: mgerdin
author | tschatzl |
---|---|
date | Wed, 20 Aug 2014 14:34:40 +0200 |
parents | 2e8f19c2feef |
children |
rev | line source |
---|---|
0 | 1 /* |
11139
2e8f19c2feef
7162400: Intermittent java.io.IOException: Bad file number during HotSpotVirtualMachine.executeCommand
allwin
parents:
1972
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:
0
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
0
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:
0
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 <windows.h> | |
32 #include <signal.h> // SIGBREAK | |
33 | |
34 // The AttachListener thread services a queue of operations. It blocks in the dequeue | |
35 // function until an operation is enqueued. A client enqueues an operation by creating | |
36 // a thread in this process using the Win32 CreateRemoteThread function. That thread | |
37 // executes a small stub generated by the client. The stub invokes the | |
38 // JVM_EnqueueOperation function which checks the operation parameters and enqueues | |
39 // the operation to the queue serviced by the attach listener. The thread created by | |
40 // the client is a native thread and is restricted to a single page of stack. To keep | |
41 // it simple operations are pre-allocated at initialization time. An enqueue thus | |
42 // takes a preallocated operation, populates the operation parameters, adds it to | |
43 // queue and wakes up the attach listener. | |
44 // | |
45 // When an operation has completed the attach listener is required to send the | |
46 // operation result and any result data to the client. In this implementation the | |
47 // client is a pipe server. In the enqueue operation it provides the name of pipe | |
48 // to this process. When the operation is completed this process opens the pipe and | |
49 // sends the result and output back to the client. Note that writing to the pipe | |
50 // (and flushing the output) is a blocking operation. This means that a non-responsive | |
51 // client could potentially hang the attach listener thread indefinitely. In that | |
52 // case no new operations would be executed but the VM would continue as normal. | |
53 // As only suitably privileged processes can open this process we concluded that | |
54 // this wasn't worth worrying about. | |
55 | |
56 | |
57 // forward reference | |
58 class Win32AttachOperation; | |
59 | |
60 | |
61 class Win32AttachListener: AllStatic { | |
62 private: | |
63 enum { | |
64 preallocate_count = 4 // number of preallocated operations | |
65 }; | |
66 | |
67 // protects the preallocated list and the operation list | |
68 static HANDLE _mutex; | |
69 | |
70 // head of preallocated operations list | |
71 static Win32AttachOperation* _avail; | |
72 | |
73 // head and tail of enqueue operations list | |
74 static Win32AttachOperation* _head; | |
75 static Win32AttachOperation* _tail; | |
76 | |
77 | |
78 static Win32AttachOperation* head() { return _head; } | |
79 static void set_head(Win32AttachOperation* head) { _head = head; } | |
80 | |
81 static Win32AttachOperation* tail() { return _tail; } | |
82 static void set_tail(Win32AttachOperation* tail) { _tail = tail; } | |
83 | |
84 | |
85 // used to wakeup the listener | |
86 static HANDLE _wakeup; | |
87 static HANDLE wakeup() { return _wakeup; } | |
88 | |
89 public: | |
90 enum { | |
91 ATTACH_ERROR_DISABLED = 100, // error codes | |
92 ATTACH_ERROR_RESOURCE = 101, | |
93 ATTACH_ERROR_ILLEGALARG = 102, | |
94 ATTACH_ERROR_INTERNAL = 103 | |
95 }; | |
96 | |
97 static int init(); | |
98 static HANDLE mutex() { return _mutex; } | |
99 | |
100 static Win32AttachOperation* available() { return _avail; } | |
101 static void set_available(Win32AttachOperation* avail) { _avail = avail; } | |
102 | |
103 // enqueue an operation to the end of the list | |
104 static int enqueue(char* cmd, char* arg1, char* arg2, char* arg3, char* pipename); | |
105 | |
106 // dequeue an operation from from head of the list | |
107 static Win32AttachOperation* dequeue(); | |
108 }; | |
109 | |
110 // statics | |
111 HANDLE Win32AttachListener::_mutex; | |
112 HANDLE Win32AttachListener::_wakeup; | |
113 Win32AttachOperation* Win32AttachListener::_avail; | |
114 Win32AttachOperation* Win32AttachListener::_head; | |
115 Win32AttachOperation* Win32AttachListener::_tail; | |
116 | |
117 | |
118 // Win32AttachOperation is an AttachOperation that additionally encapsulates the name | |
119 // of a pipe which is used to send the operation reply/output to the client. | |
120 // Win32AttachOperation can also be linked in a list. | |
121 | |
122 class Win32AttachOperation: public AttachOperation { | |
123 private: | |
124 friend class Win32AttachListener; | |
125 | |
126 enum { | |
127 pipe_name_max = 256 // maximum pipe name | |
128 }; | |
129 | |
130 char _pipe[pipe_name_max+1]; | |
131 | |
132 const char* pipe() const { return _pipe; } | |
133 void set_pipe(const char* pipe) { | |
134 assert(strlen(pipe) <= pipe_name_max, "execeds maximum length of pipe name"); | |
135 strcpy(_pipe, pipe); | |
136 } | |
137 | |
138 HANDLE open_pipe(); | |
139 static BOOL write_pipe(HANDLE hPipe, char* buf, int len); | |
140 | |
141 Win32AttachOperation* _next; | |
142 | |
143 Win32AttachOperation* next() const { return _next; } | |
144 void set_next(Win32AttachOperation* next) { _next = next; } | |
145 | |
146 // noarg constructor as operation is preallocated | |
147 Win32AttachOperation() : AttachOperation("<noname>") { | |
148 set_pipe("<nopipe>"); | |
149 set_next(NULL); | |
150 } | |
151 | |
152 public: | |
153 void Win32AttachOperation::complete(jint result, bufferedStream* result_stream); | |
154 }; | |
155 | |
156 | |
157 // preallocate the required number of operations | |
158 int Win32AttachListener::init() { | |
159 _mutex = (void*)::CreateMutex(NULL, FALSE, NULL); | |
160 guarantee(_mutex != (HANDLE)NULL, "mutex creation failed"); | |
161 | |
162 _wakeup = ::CreateSemaphore(NULL, 0, 1, NULL); | |
163 guarantee(_wakeup != (HANDLE)NULL, "semaphore creation failed"); | |
164 | |
165 set_head(NULL); | |
166 set_tail(NULL); | |
167 | |
168 // preallocate a few operations | |
169 set_available(NULL); | |
170 for (int i=0; i<preallocate_count; i++) { | |
171 Win32AttachOperation* op = new Win32AttachOperation(); | |
172 op->set_next(available()); | |
173 set_available(op); | |
174 } | |
175 | |
176 return 0; | |
177 } | |
178 | |
179 // Enqueue an operation. This is called from a native thread that is not attached to VM. | |
180 // Also we need to be careful not to execute anything that results in more than a 4k stack. | |
181 // | |
182 int Win32AttachListener::enqueue(char* cmd, char* arg0, char* arg1, char* arg2, char* pipename) { | |
183 // listener not running | |
184 if (!AttachListener::is_initialized()) { | |
185 return ATTACH_ERROR_DISABLED; | |
186 } | |
187 | |
188 // check that all paramteres to the operation | |
189 if (strlen(cmd) > AttachOperation::name_length_max) return ATTACH_ERROR_ILLEGALARG; | |
190 if (strlen(arg0) > AttachOperation::arg_length_max) return ATTACH_ERROR_ILLEGALARG; | |
191 if (strlen(arg0) > AttachOperation::arg_length_max) return ATTACH_ERROR_ILLEGALARG; | |
192 if (strlen(pipename) > Win32AttachOperation::pipe_name_max) return ATTACH_ERROR_ILLEGALARG; | |
193 | |
194 // check for a well-formed pipename | |
195 if (strstr(pipename, "\\\\.\\pipe\\") != pipename) return ATTACH_ERROR_ILLEGALARG; | |
196 | |
197 // grab the lock for the list | |
198 DWORD res = ::WaitForSingleObject(mutex(), INFINITE); | |
199 if (res != WAIT_OBJECT_0) { | |
200 return ATTACH_ERROR_INTERNAL; | |
201 } | |
202 | |
203 // try to get an operation from the available list | |
204 Win32AttachOperation* op = available(); | |
205 if (op != NULL) { | |
206 set_available(op->next()); | |
207 | |
208 // add to end (tail) of list | |
209 op->set_next(NULL); | |
210 if (tail() == NULL) { | |
211 set_head(op); | |
212 } else { | |
213 tail()->set_next(op); | |
214 } | |
215 set_tail(op); | |
216 | |
217 op->set_name(cmd); | |
218 op->set_arg(0, arg0); | |
219 op->set_arg(1, arg1); | |
220 op->set_arg(2, arg2); | |
221 op->set_pipe(pipename); | |
222 | |
223 // wakeup the thread waiting for operations | |
224 ::ReleaseSemaphore(wakeup(), 1, NULL); | |
225 } | |
226 ::ReleaseMutex(mutex()); | |
227 | |
228 return (op != NULL) ? 0 : ATTACH_ERROR_RESOURCE; | |
229 } | |
230 | |
231 | |
232 // dequeue the operation from the head of the operation list. If | |
233 Win32AttachOperation* Win32AttachListener::dequeue() { | |
234 for (;;) { | |
235 DWORD res = ::WaitForSingleObject(wakeup(), INFINITE); | |
236 guarantee(res == WAIT_OBJECT_0, "wait failed"); | |
237 | |
238 res = ::WaitForSingleObject(mutex(), INFINITE); | |
239 guarantee(res == WAIT_OBJECT_0, "wait failed"); | |
240 | |
241 Win32AttachOperation* op = head(); | |
242 if (op != NULL) { | |
243 set_head(op->next()); | |
244 if (head() == NULL) { // list is empty | |
245 set_tail(NULL); | |
246 } | |
247 } | |
248 ::ReleaseMutex(mutex()); | |
249 | |
250 if (op != NULL) { | |
251 return op; | |
252 } | |
253 } | |
254 } | |
255 | |
256 | |
257 // open the pipe to the client | |
258 HANDLE Win32AttachOperation::open_pipe() { | |
259 HANDLE hPipe; | |
260 | |
261 hPipe = ::CreateFile( pipe(), // pipe name | |
262 GENERIC_WRITE, // write only | |
263 0, // no sharing | |
264 NULL, // default security attributes | |
265 OPEN_EXISTING, // opens existing pipe | |
266 0, // default attributes | |
267 NULL); // no template file | |
268 | |
269 if (hPipe != INVALID_HANDLE_VALUE) { | |
270 // shouldn't happen as there is a pipe created per operation | |
271 if (::GetLastError() == ERROR_PIPE_BUSY) { | |
272 return INVALID_HANDLE_VALUE; | |
273 } | |
274 } | |
275 return hPipe; | |
276 } | |
277 | |
278 // write to the pipe | |
279 BOOL Win32AttachOperation::write_pipe(HANDLE hPipe, char* buf, int len) { | |
280 do { | |
281 DWORD nwrote; | |
282 | |
283 BOOL fSuccess = WriteFile( hPipe, // pipe handle | |
284 (LPCVOID)buf, // message | |
285 (DWORD)len, // message length | |
286 &nwrote, // bytes written | |
287 NULL); // not overlapped | |
288 if (!fSuccess) { | |
289 return fSuccess; | |
290 } | |
291 buf += nwrote; | |
292 len -= nwrote; | |
293 } | |
294 while (len > 0); | |
295 return TRUE; | |
296 } | |
297 | |
298 // Complete the operation: | |
299 // - open the pipe to the client | |
300 // - write the operation result (a jint) | |
301 // - write the operation output (the result stream) | |
302 // | |
303 void Win32AttachOperation::complete(jint result, bufferedStream* result_stream) { | |
304 JavaThread* thread = JavaThread::current(); | |
305 ThreadBlockInVM tbivm(thread); | |
306 | |
307 thread->set_suspend_equivalent(); | |
308 // cleared by handle_special_suspend_equivalent_condition() or | |
309 // java_suspend_self() via check_and_wait_while_suspended() | |
310 | |
311 HANDLE hPipe = open_pipe(); | |
312 if (hPipe != INVALID_HANDLE_VALUE) { | |
313 BOOL fSuccess; | |
314 | |
315 char msg[32]; | |
316 sprintf(msg, "%d\n", result); | |
317 | |
318 fSuccess = write_pipe(hPipe, msg, (int)strlen(msg)); | |
319 if (fSuccess) { | |
320 write_pipe(hPipe, (char*) result_stream->base(), (int)(result_stream->size())); | |
321 } | |
322 | |
323 // Need to flush buffers | |
324 FlushFileBuffers(hPipe); | |
325 CloseHandle(hPipe); | |
326 } | |
327 | |
328 DWORD res = ::WaitForSingleObject(Win32AttachListener::mutex(), INFINITE); | |
329 if (res == WAIT_OBJECT_0) { | |
330 | |
331 // put the operation back on the available list | |
332 set_next(Win32AttachListener::available()); | |
333 Win32AttachListener::set_available(this); | |
334 | |
335 ::ReleaseMutex(Win32AttachListener::mutex()); | |
336 } | |
337 | |
338 // were we externally suspended while we were waiting? | |
339 thread->check_and_wait_while_suspended(); | |
340 } | |
341 | |
342 | |
343 // AttachOperation functions | |
344 | |
345 AttachOperation* AttachListener::dequeue() { | |
346 JavaThread* thread = JavaThread::current(); | |
347 ThreadBlockInVM tbivm(thread); | |
348 | |
349 thread->set_suspend_equivalent(); | |
350 // cleared by handle_special_suspend_equivalent_condition() or | |
351 // java_suspend_self() via check_and_wait_while_suspended() | |
352 | |
353 AttachOperation* op = Win32AttachListener::dequeue(); | |
354 | |
355 // were we externally suspended while we were waiting? | |
356 thread->check_and_wait_while_suspended(); | |
357 | |
358 return op; | |
359 } | |
360 | |
11139
2e8f19c2feef
7162400: Intermittent java.io.IOException: Bad file number during HotSpotVirtualMachine.executeCommand
allwin
parents:
1972
diff
changeset
|
361 void AttachListener::vm_start() { |
2e8f19c2feef
7162400: Intermittent java.io.IOException: Bad file number during HotSpotVirtualMachine.executeCommand
allwin
parents:
1972
diff
changeset
|
362 // nothing to do |
2e8f19c2feef
7162400: Intermittent java.io.IOException: Bad file number during HotSpotVirtualMachine.executeCommand
allwin
parents:
1972
diff
changeset
|
363 } |
2e8f19c2feef
7162400: Intermittent java.io.IOException: Bad file number during HotSpotVirtualMachine.executeCommand
allwin
parents:
1972
diff
changeset
|
364 |
0 | 365 int AttachListener::pd_init() { |
366 return Win32AttachListener::init(); | |
367 } | |
368 | |
369 // always startup on Windows NT/2000/XP | |
370 bool AttachListener::init_at_startup() { | |
371 return os::win32::is_nt(); | |
372 } | |
373 | |
374 // no trigger mechanism on Windows to start Attach Listener lazily | |
375 bool AttachListener::is_init_trigger() { | |
376 return false; | |
377 } | |
378 | |
379 void AttachListener::abort() { | |
380 // nothing to do | |
381 } | |
382 | |
383 void AttachListener::pd_data_dump() { | |
384 os::signal_notify(SIGBREAK); | |
385 } | |
386 | |
387 AttachOperationFunctionInfo* AttachListener::pd_find_operation(const char* n) { | |
388 return NULL; | |
389 } | |
390 | |
391 jint AttachListener::pd_set_flag(AttachOperation* op, outputStream* out) { | |
392 out->print_cr("flag '%s' cannot be changed", op->arg(0)); | |
393 return JNI_ERR; | |
394 } | |
395 | |
396 void AttachListener::pd_detachall() { | |
397 // do nothing for now | |
398 } | |
399 | |
400 // Native thread started by remote client executes this. | |
401 extern "C" { | |
402 JNIEXPORT jint JNICALL | |
403 JVM_EnqueueOperation(char* cmd, char* arg0, char* arg1, char* arg2, char* pipename) { | |
404 return (jint)Win32AttachListener::enqueue(cmd, arg0, arg1, arg2, pipename); | |
405 } | |
406 | |
407 } // extern |