src/os/windows/vm/attachListener_windows.cpp

Wed, 27 Apr 2016 01:25:04 +0800

author
aoqi
date
Wed, 27 Apr 2016 01:25:04 +0800
changeset 0
f90c822e73f8
child 6876
710a3c8b516e
permissions
-rw-r--r--

Initial load
http://hg.openjdk.java.net/jdk8u/jdk8u/hotspot/
changeset: 6782:28b50d07f6f8
tag: jdk8u25-b17

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

mercurial