1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/os/windows/vm/attachListener_windows.cpp Wed Apr 27 01:25:04 2016 +0800 1.3 @@ -0,0 +1,407 @@ 1.4 +/* 1.5 + * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. 1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 1.7 + * 1.8 + * This code is free software; you can redistribute it and/or modify it 1.9 + * under the terms of the GNU General Public License version 2 only, as 1.10 + * published by the Free Software Foundation. 1.11 + * 1.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 1.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1.15 + * version 2 for more details (a copy is included in the LICENSE file that 1.16 + * accompanied this code). 1.17 + * 1.18 + * You should have received a copy of the GNU General Public License version 1.19 + * 2 along with this work; if not, write to the Free Software Foundation, 1.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 1.21 + * 1.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 1.23 + * or visit www.oracle.com if you need additional information or have any 1.24 + * questions. 1.25 + * 1.26 + */ 1.27 + 1.28 +#include "precompiled.hpp" 1.29 +#include "runtime/interfaceSupport.hpp" 1.30 +#include "runtime/os.hpp" 1.31 +#include "services/attachListener.hpp" 1.32 +#include "services/dtraceAttacher.hpp" 1.33 + 1.34 +#include <windows.h> 1.35 +#include <signal.h> // SIGBREAK 1.36 + 1.37 +// The AttachListener thread services a queue of operations. It blocks in the dequeue 1.38 +// function until an operation is enqueued. A client enqueues an operation by creating 1.39 +// a thread in this process using the Win32 CreateRemoteThread function. That thread 1.40 +// executes a small stub generated by the client. The stub invokes the 1.41 +// JVM_EnqueueOperation function which checks the operation parameters and enqueues 1.42 +// the operation to the queue serviced by the attach listener. The thread created by 1.43 +// the client is a native thread and is restricted to a single page of stack. To keep 1.44 +// it simple operations are pre-allocated at initialization time. An enqueue thus 1.45 +// takes a preallocated operation, populates the operation parameters, adds it to 1.46 +// queue and wakes up the attach listener. 1.47 +// 1.48 +// When an operation has completed the attach listener is required to send the 1.49 +// operation result and any result data to the client. In this implementation the 1.50 +// client is a pipe server. In the enqueue operation it provides the name of pipe 1.51 +// to this process. When the operation is completed this process opens the pipe and 1.52 +// sends the result and output back to the client. Note that writing to the pipe 1.53 +// (and flushing the output) is a blocking operation. This means that a non-responsive 1.54 +// client could potentially hang the attach listener thread indefinitely. In that 1.55 +// case no new operations would be executed but the VM would continue as normal. 1.56 +// As only suitably privileged processes can open this process we concluded that 1.57 +// this wasn't worth worrying about. 1.58 + 1.59 + 1.60 +// forward reference 1.61 +class Win32AttachOperation; 1.62 + 1.63 + 1.64 +class Win32AttachListener: AllStatic { 1.65 + private: 1.66 + enum { 1.67 + preallocate_count = 4 // number of preallocated operations 1.68 + }; 1.69 + 1.70 + // protects the preallocated list and the operation list 1.71 + static HANDLE _mutex; 1.72 + 1.73 + // head of preallocated operations list 1.74 + static Win32AttachOperation* _avail; 1.75 + 1.76 + // head and tail of enqueue operations list 1.77 + static Win32AttachOperation* _head; 1.78 + static Win32AttachOperation* _tail; 1.79 + 1.80 + 1.81 + static Win32AttachOperation* head() { return _head; } 1.82 + static void set_head(Win32AttachOperation* head) { _head = head; } 1.83 + 1.84 + static Win32AttachOperation* tail() { return _tail; } 1.85 + static void set_tail(Win32AttachOperation* tail) { _tail = tail; } 1.86 + 1.87 + 1.88 + // used to wakeup the listener 1.89 + static HANDLE _wakeup; 1.90 + static HANDLE wakeup() { return _wakeup; } 1.91 + 1.92 + public: 1.93 + enum { 1.94 + ATTACH_ERROR_DISABLED = 100, // error codes 1.95 + ATTACH_ERROR_RESOURCE = 101, 1.96 + ATTACH_ERROR_ILLEGALARG = 102, 1.97 + ATTACH_ERROR_INTERNAL = 103 1.98 + }; 1.99 + 1.100 + static int init(); 1.101 + static HANDLE mutex() { return _mutex; } 1.102 + 1.103 + static Win32AttachOperation* available() { return _avail; } 1.104 + static void set_available(Win32AttachOperation* avail) { _avail = avail; } 1.105 + 1.106 + // enqueue an operation to the end of the list 1.107 + static int enqueue(char* cmd, char* arg1, char* arg2, char* arg3, char* pipename); 1.108 + 1.109 + // dequeue an operation from from head of the list 1.110 + static Win32AttachOperation* dequeue(); 1.111 +}; 1.112 + 1.113 +// statics 1.114 +HANDLE Win32AttachListener::_mutex; 1.115 +HANDLE Win32AttachListener::_wakeup; 1.116 +Win32AttachOperation* Win32AttachListener::_avail; 1.117 +Win32AttachOperation* Win32AttachListener::_head; 1.118 +Win32AttachOperation* Win32AttachListener::_tail; 1.119 + 1.120 + 1.121 +// Win32AttachOperation is an AttachOperation that additionally encapsulates the name 1.122 +// of a pipe which is used to send the operation reply/output to the client. 1.123 +// Win32AttachOperation can also be linked in a list. 1.124 + 1.125 +class Win32AttachOperation: public AttachOperation { 1.126 + private: 1.127 + friend class Win32AttachListener; 1.128 + 1.129 + enum { 1.130 + pipe_name_max = 256 // maximum pipe name 1.131 + }; 1.132 + 1.133 + char _pipe[pipe_name_max+1]; 1.134 + 1.135 + const char* pipe() const { return _pipe; } 1.136 + void set_pipe(const char* pipe) { 1.137 + assert(strlen(pipe) <= pipe_name_max, "execeds maximum length of pipe name"); 1.138 + strcpy(_pipe, pipe); 1.139 + } 1.140 + 1.141 + HANDLE open_pipe(); 1.142 + static BOOL write_pipe(HANDLE hPipe, char* buf, int len); 1.143 + 1.144 + Win32AttachOperation* _next; 1.145 + 1.146 + Win32AttachOperation* next() const { return _next; } 1.147 + void set_next(Win32AttachOperation* next) { _next = next; } 1.148 + 1.149 + // noarg constructor as operation is preallocated 1.150 + Win32AttachOperation() : AttachOperation("<noname>") { 1.151 + set_pipe("<nopipe>"); 1.152 + set_next(NULL); 1.153 + } 1.154 + 1.155 + public: 1.156 + void Win32AttachOperation::complete(jint result, bufferedStream* result_stream); 1.157 +}; 1.158 + 1.159 + 1.160 +// preallocate the required number of operations 1.161 +int Win32AttachListener::init() { 1.162 + _mutex = (void*)::CreateMutex(NULL, FALSE, NULL); 1.163 + guarantee(_mutex != (HANDLE)NULL, "mutex creation failed"); 1.164 + 1.165 + _wakeup = ::CreateSemaphore(NULL, 0, 1, NULL); 1.166 + guarantee(_wakeup != (HANDLE)NULL, "semaphore creation failed"); 1.167 + 1.168 + set_head(NULL); 1.169 + set_tail(NULL); 1.170 + 1.171 + // preallocate a few operations 1.172 + set_available(NULL); 1.173 + for (int i=0; i<preallocate_count; i++) { 1.174 + Win32AttachOperation* op = new Win32AttachOperation(); 1.175 + op->set_next(available()); 1.176 + set_available(op); 1.177 + } 1.178 + 1.179 + return 0; 1.180 +} 1.181 + 1.182 +// Enqueue an operation. This is called from a native thread that is not attached to VM. 1.183 +// Also we need to be careful not to execute anything that results in more than a 4k stack. 1.184 +// 1.185 +int Win32AttachListener::enqueue(char* cmd, char* arg0, char* arg1, char* arg2, char* pipename) { 1.186 + // listener not running 1.187 + if (!AttachListener::is_initialized()) { 1.188 + return ATTACH_ERROR_DISABLED; 1.189 + } 1.190 + 1.191 + // check that all paramteres to the operation 1.192 + if (strlen(cmd) > AttachOperation::name_length_max) return ATTACH_ERROR_ILLEGALARG; 1.193 + if (strlen(arg0) > AttachOperation::arg_length_max) return ATTACH_ERROR_ILLEGALARG; 1.194 + if (strlen(arg0) > AttachOperation::arg_length_max) return ATTACH_ERROR_ILLEGALARG; 1.195 + if (strlen(pipename) > Win32AttachOperation::pipe_name_max) return ATTACH_ERROR_ILLEGALARG; 1.196 + 1.197 + // check for a well-formed pipename 1.198 + if (strstr(pipename, "\\\\.\\pipe\\") != pipename) return ATTACH_ERROR_ILLEGALARG; 1.199 + 1.200 + // grab the lock for the list 1.201 + DWORD res = ::WaitForSingleObject(mutex(), INFINITE); 1.202 + if (res != WAIT_OBJECT_0) { 1.203 + return ATTACH_ERROR_INTERNAL; 1.204 + } 1.205 + 1.206 + // try to get an operation from the available list 1.207 + Win32AttachOperation* op = available(); 1.208 + if (op != NULL) { 1.209 + set_available(op->next()); 1.210 + 1.211 + // add to end (tail) of list 1.212 + op->set_next(NULL); 1.213 + if (tail() == NULL) { 1.214 + set_head(op); 1.215 + } else { 1.216 + tail()->set_next(op); 1.217 + } 1.218 + set_tail(op); 1.219 + 1.220 + op->set_name(cmd); 1.221 + op->set_arg(0, arg0); 1.222 + op->set_arg(1, arg1); 1.223 + op->set_arg(2, arg2); 1.224 + op->set_pipe(pipename); 1.225 + 1.226 + // wakeup the thread waiting for operations 1.227 + ::ReleaseSemaphore(wakeup(), 1, NULL); 1.228 + } 1.229 + ::ReleaseMutex(mutex()); 1.230 + 1.231 + return (op != NULL) ? 0 : ATTACH_ERROR_RESOURCE; 1.232 +} 1.233 + 1.234 + 1.235 +// dequeue the operation from the head of the operation list. If 1.236 +Win32AttachOperation* Win32AttachListener::dequeue() { 1.237 + for (;;) { 1.238 + DWORD res = ::WaitForSingleObject(wakeup(), INFINITE); 1.239 + guarantee(res == WAIT_OBJECT_0, "wait failed"); 1.240 + 1.241 + res = ::WaitForSingleObject(mutex(), INFINITE); 1.242 + guarantee(res == WAIT_OBJECT_0, "wait failed"); 1.243 + 1.244 + Win32AttachOperation* op = head(); 1.245 + if (op != NULL) { 1.246 + set_head(op->next()); 1.247 + if (head() == NULL) { // list is empty 1.248 + set_tail(NULL); 1.249 + } 1.250 + } 1.251 + ::ReleaseMutex(mutex()); 1.252 + 1.253 + if (op != NULL) { 1.254 + return op; 1.255 + } 1.256 + } 1.257 +} 1.258 + 1.259 + 1.260 +// open the pipe to the client 1.261 +HANDLE Win32AttachOperation::open_pipe() { 1.262 + HANDLE hPipe; 1.263 + 1.264 + hPipe = ::CreateFile( pipe(), // pipe name 1.265 + GENERIC_WRITE, // write only 1.266 + 0, // no sharing 1.267 + NULL, // default security attributes 1.268 + OPEN_EXISTING, // opens existing pipe 1.269 + 0, // default attributes 1.270 + NULL); // no template file 1.271 + 1.272 + if (hPipe != INVALID_HANDLE_VALUE) { 1.273 + // shouldn't happen as there is a pipe created per operation 1.274 + if (::GetLastError() == ERROR_PIPE_BUSY) { 1.275 + return INVALID_HANDLE_VALUE; 1.276 + } 1.277 + } 1.278 + return hPipe; 1.279 +} 1.280 + 1.281 +// write to the pipe 1.282 +BOOL Win32AttachOperation::write_pipe(HANDLE hPipe, char* buf, int len) { 1.283 + do { 1.284 + DWORD nwrote; 1.285 + 1.286 + BOOL fSuccess = WriteFile( hPipe, // pipe handle 1.287 + (LPCVOID)buf, // message 1.288 + (DWORD)len, // message length 1.289 + &nwrote, // bytes written 1.290 + NULL); // not overlapped 1.291 + if (!fSuccess) { 1.292 + return fSuccess; 1.293 + } 1.294 + buf += nwrote; 1.295 + len -= nwrote; 1.296 + } 1.297 + while (len > 0); 1.298 + return TRUE; 1.299 +} 1.300 + 1.301 +// Complete the operation: 1.302 +// - open the pipe to the client 1.303 +// - write the operation result (a jint) 1.304 +// - write the operation output (the result stream) 1.305 +// 1.306 +void Win32AttachOperation::complete(jint result, bufferedStream* result_stream) { 1.307 + JavaThread* thread = JavaThread::current(); 1.308 + ThreadBlockInVM tbivm(thread); 1.309 + 1.310 + thread->set_suspend_equivalent(); 1.311 + // cleared by handle_special_suspend_equivalent_condition() or 1.312 + // java_suspend_self() via check_and_wait_while_suspended() 1.313 + 1.314 + HANDLE hPipe = open_pipe(); 1.315 + if (hPipe != INVALID_HANDLE_VALUE) { 1.316 + BOOL fSuccess; 1.317 + 1.318 + char msg[32]; 1.319 + sprintf(msg, "%d\n", result); 1.320 + 1.321 + fSuccess = write_pipe(hPipe, msg, (int)strlen(msg)); 1.322 + if (fSuccess) { 1.323 + write_pipe(hPipe, (char*) result_stream->base(), (int)(result_stream->size())); 1.324 + } 1.325 + 1.326 + // Need to flush buffers 1.327 + FlushFileBuffers(hPipe); 1.328 + CloseHandle(hPipe); 1.329 + } 1.330 + 1.331 + DWORD res = ::WaitForSingleObject(Win32AttachListener::mutex(), INFINITE); 1.332 + if (res == WAIT_OBJECT_0) { 1.333 + 1.334 + // put the operation back on the available list 1.335 + set_next(Win32AttachListener::available()); 1.336 + Win32AttachListener::set_available(this); 1.337 + 1.338 + ::ReleaseMutex(Win32AttachListener::mutex()); 1.339 + } 1.340 + 1.341 + // were we externally suspended while we were waiting? 1.342 + thread->check_and_wait_while_suspended(); 1.343 +} 1.344 + 1.345 + 1.346 +// AttachOperation functions 1.347 + 1.348 +AttachOperation* AttachListener::dequeue() { 1.349 + JavaThread* thread = JavaThread::current(); 1.350 + ThreadBlockInVM tbivm(thread); 1.351 + 1.352 + thread->set_suspend_equivalent(); 1.353 + // cleared by handle_special_suspend_equivalent_condition() or 1.354 + // java_suspend_self() via check_and_wait_while_suspended() 1.355 + 1.356 + AttachOperation* op = Win32AttachListener::dequeue(); 1.357 + 1.358 + // were we externally suspended while we were waiting? 1.359 + thread->check_and_wait_while_suspended(); 1.360 + 1.361 + return op; 1.362 +} 1.363 + 1.364 +void AttachListener::vm_start() { 1.365 + // nothing to do 1.366 +} 1.367 + 1.368 +int AttachListener::pd_init() { 1.369 + return Win32AttachListener::init(); 1.370 +} 1.371 + 1.372 +// always startup on Windows NT/2000/XP 1.373 +bool AttachListener::init_at_startup() { 1.374 + return os::win32::is_nt(); 1.375 +} 1.376 + 1.377 +// no trigger mechanism on Windows to start Attach Listener lazily 1.378 +bool AttachListener::is_init_trigger() { 1.379 + return false; 1.380 +} 1.381 + 1.382 +void AttachListener::abort() { 1.383 + // nothing to do 1.384 +} 1.385 + 1.386 +void AttachListener::pd_data_dump() { 1.387 + os::signal_notify(SIGBREAK); 1.388 +} 1.389 + 1.390 +AttachOperationFunctionInfo* AttachListener::pd_find_operation(const char* n) { 1.391 + return NULL; 1.392 +} 1.393 + 1.394 +jint AttachListener::pd_set_flag(AttachOperation* op, outputStream* out) { 1.395 + out->print_cr("flag '%s' cannot be changed", op->arg(0)); 1.396 + return JNI_ERR; 1.397 +} 1.398 + 1.399 +void AttachListener::pd_detachall() { 1.400 + // do nothing for now 1.401 +} 1.402 + 1.403 +// Native thread started by remote client executes this. 1.404 +extern "C" { 1.405 + JNIEXPORT jint JNICALL 1.406 + JVM_EnqueueOperation(char* cmd, char* arg0, char* arg1, char* arg2, char* pipename) { 1.407 + return (jint)Win32AttachListener::enqueue(cmd, arg0, arg1, arg2, pipename); 1.408 + } 1.409 + 1.410 +} // extern