src/os/windows/vm/attachListener_windows.cpp

Fri, 30 Nov 2012 15:23:16 -0800

author
twisti
date
Fri, 30 Nov 2012 15:23:16 -0800
changeset 4318
cd3d6a6b95d9
parent 2314
f95d63e2154a
child 5412
2e8f19c2feef
permissions
-rw-r--r--

8003240: x86: move MacroAssembler into separate file
Reviewed-by: kvn

     1 /*
     2  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
     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  *
    19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    20  * or visit www.oracle.com if you need additional information or have any
    21  * questions.
    22  *
    23  */
    25 #include "precompiled.hpp"
    26 #include "runtime/interfaceSupport.hpp"
    27 #include "runtime/os.hpp"
    28 #include "services/attachListener.hpp"
    29 #include "services/dtraceAttacher.hpp"
    31 #include <windows.h>
    32 #include <signal.h>             // SIGBREAK
    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.
    57 // forward reference
    58 class Win32AttachOperation;
    61 class Win32AttachListener: AllStatic {
    62  private:
    63   enum {
    64     preallocate_count = 4                   // number of preallocated operations
    65   };
    67   // protects the preallocated list and the operation list
    68   static HANDLE _mutex;
    70   // head of preallocated operations list
    71   static Win32AttachOperation* _avail;
    73   // head and tail of enqueue operations list
    74   static Win32AttachOperation* _head;
    75   static Win32AttachOperation* _tail;
    78   static Win32AttachOperation* head()                       { return _head; }
    79   static void set_head(Win32AttachOperation* head)          { _head = head; }
    81   static Win32AttachOperation* tail()                       { return _tail; }
    82   static void set_tail(Win32AttachOperation* tail)          { _tail = tail; }
    85   // used to wakeup the listener
    86   static HANDLE _wakeup;
    87   static HANDLE wakeup()                                    { return _wakeup; }
    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   };
    97   static int init();
    98   static HANDLE mutex()                                     { return _mutex; }
   100   static Win32AttachOperation* available()                  { return _avail; }
   101   static void set_available(Win32AttachOperation* avail)    { _avail = avail; }
   103   // enqueue an operation to the end of the list
   104   static int enqueue(char* cmd, char* arg1, char* arg2, char* arg3, char* pipename);
   106   // dequeue an operation from from head of the list
   107   static Win32AttachOperation* dequeue();
   108 };
   110 // statics
   111 HANDLE Win32AttachListener::_mutex;
   112 HANDLE Win32AttachListener::_wakeup;
   113 Win32AttachOperation* Win32AttachListener::_avail;
   114 Win32AttachOperation* Win32AttachListener::_head;
   115 Win32AttachOperation* Win32AttachListener::_tail;
   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.
   122 class Win32AttachOperation: public AttachOperation {
   123  private:
   124   friend class Win32AttachListener;
   126   enum {
   127     pipe_name_max = 256             // maximum pipe name
   128   };
   130   char _pipe[pipe_name_max+1];
   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   }
   138   HANDLE open_pipe();
   139   static BOOL write_pipe(HANDLE hPipe, char* buf, int len);
   141   Win32AttachOperation* _next;
   143   Win32AttachOperation* next() const                    { return _next; }
   144   void set_next(Win32AttachOperation* next)             { _next = next; }
   146   // noarg constructor as operation is preallocated
   147   Win32AttachOperation() : AttachOperation("<noname>") {
   148     set_pipe("<nopipe>");
   149     set_next(NULL);
   150   }
   152  public:
   153   void Win32AttachOperation::complete(jint result, bufferedStream* result_stream);
   154 };
   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");
   162   _wakeup = ::CreateSemaphore(NULL, 0, 1, NULL);
   163   guarantee(_wakeup != (HANDLE)NULL, "semaphore creation failed");
   165   set_head(NULL);
   166   set_tail(NULL);
   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   }
   176   return 0;
   177 }
   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   }
   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;
   194   // check for a well-formed pipename
   195   if (strstr(pipename, "\\\\.\\pipe\\") != pipename) return ATTACH_ERROR_ILLEGALARG;
   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   }
   203   // try to get an operation from the available list
   204   Win32AttachOperation* op = available();
   205   if (op != NULL) {
   206     set_available(op->next());
   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);
   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);
   223     // wakeup the thread waiting for operations
   224     ::ReleaseSemaphore(wakeup(), 1, NULL);
   225   }
   226   ::ReleaseMutex(mutex());
   228   return (op != NULL) ? 0 : ATTACH_ERROR_RESOURCE;
   229 }
   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");
   238     res = ::WaitForSingleObject(mutex(), INFINITE);
   239     guarantee(res == WAIT_OBJECT_0, "wait failed");
   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());
   250     if (op != NULL) {
   251       return op;
   252     }
   253   }
   254 }
   257 // open the pipe to the client
   258 HANDLE Win32AttachOperation::open_pipe() {
   259   HANDLE hPipe;
   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
   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 }
   278 // write to the pipe
   279 BOOL Win32AttachOperation::write_pipe(HANDLE hPipe, char* buf, int len) {
   280   do {
   281     DWORD nwrote;
   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 }
   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);
   307   thread->set_suspend_equivalent();
   308   // cleared by handle_special_suspend_equivalent_condition() or
   309   // java_suspend_self() via check_and_wait_while_suspended()
   311   HANDLE hPipe = open_pipe();
   312   if (hPipe != INVALID_HANDLE_VALUE) {
   313     BOOL fSuccess;
   315     char msg[32];
   316     sprintf(msg, "%d\n", result);
   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     }
   323     // Need to flush buffers
   324     FlushFileBuffers(hPipe);
   325     CloseHandle(hPipe);
   326   }
   328   DWORD res = ::WaitForSingleObject(Win32AttachListener::mutex(), INFINITE);
   329   if (res == WAIT_OBJECT_0) {
   331     // put the operation back on the available list
   332     set_next(Win32AttachListener::available());
   333     Win32AttachListener::set_available(this);
   335     ::ReleaseMutex(Win32AttachListener::mutex());
   336   }
   338   // were we externally suspended while we were waiting?
   339   thread->check_and_wait_while_suspended();
   340 }
   343 // AttachOperation functions
   345 AttachOperation* AttachListener::dequeue() {
   346   JavaThread* thread = JavaThread::current();
   347   ThreadBlockInVM tbivm(thread);
   349   thread->set_suspend_equivalent();
   350   // cleared by handle_special_suspend_equivalent_condition() or
   351   // java_suspend_self() via check_and_wait_while_suspended()
   353   AttachOperation* op = Win32AttachListener::dequeue();
   355   // were we externally suspended while we were waiting?
   356   thread->check_and_wait_while_suspended();
   358   return op;
   359 }
   361 int AttachListener::pd_init() {
   362   return Win32AttachListener::init();
   363 }
   365 // always startup on Windows NT/2000/XP
   366 bool AttachListener::init_at_startup() {
   367   return os::win32::is_nt();
   368 }
   370 // no trigger mechanism on Windows to start Attach Listener lazily
   371 bool AttachListener::is_init_trigger() {
   372   return false;
   373 }
   375 void AttachListener::abort() {
   376   // nothing to do
   377 }
   379 void AttachListener::pd_data_dump() {
   380   os::signal_notify(SIGBREAK);
   381 }
   383 AttachOperationFunctionInfo* AttachListener::pd_find_operation(const char* n) {
   384   return NULL;
   385 }
   387 jint AttachListener::pd_set_flag(AttachOperation* op, outputStream* out) {
   388   out->print_cr("flag '%s' cannot be changed", op->arg(0));
   389   return JNI_ERR;
   390 }
   392 void AttachListener::pd_detachall() {
   393   // do nothing for now
   394 }
   396 // Native thread started by remote client executes this.
   397 extern "C" {
   398   JNIEXPORT jint JNICALL
   399     JVM_EnqueueOperation(char* cmd, char* arg0, char* arg1, char* arg2, char* pipename) {
   400       return (jint)Win32AttachListener::enqueue(cmd, arg0, arg1, arg2, pipename);
   401     }
   403 } // extern

mercurial