src/os/windows/vm/attachListener_windows.cpp

Thu, 27 May 2010 19:08:38 -0700

author
trims
date
Thu, 27 May 2010 19:08:38 -0700
changeset 1907
c18cbe5936b8
parent 435
a61af66fc99e
child 2314
f95d63e2154a
permissions
-rw-r--r--

6941466: Oracle rebranding changes for Hotspot repositories
Summary: Change all the Sun copyrights to Oracle copyright
Reviewed-by: ohair

     1 /*
     2  * Copyright (c) 2005, 2006, 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 "incls/_precompiled.incl"
    26 # include "incls/_attachListener_windows.cpp.incl"
    28 #include <windows.h>
    29 #include <signal.h>             // SIGBREAK
    31 // The AttachListener thread services a queue of operations. It blocks in the dequeue
    32 // function until an operation is enqueued. A client enqueues an operation by creating
    33 // a thread in this process using the Win32 CreateRemoteThread function. That thread
    34 // executes a small stub generated by the client. The stub invokes the
    35 // JVM_EnqueueOperation function which checks the operation parameters and enqueues
    36 // the operation to the queue serviced by the attach listener. The thread created by
    37 // the client is a native thread and is restricted to a single page of stack. To keep
    38 // it simple operations are pre-allocated at initialization time. An enqueue thus
    39 // takes a preallocated operation, populates the operation parameters, adds it to
    40 // queue and wakes up the attach listener.
    41 //
    42 // When an operation has completed the attach listener is required to send the
    43 // operation result and any result data to the client. In this implementation the
    44 // client is a pipe server. In the enqueue operation it provides the name of pipe
    45 // to this process. When the operation is completed this process opens the pipe and
    46 // sends the result and output back to the client. Note that writing to the pipe
    47 // (and flushing the output) is a blocking operation. This means that a non-responsive
    48 // client could potentially hang the attach listener thread indefinitely. In that
    49 // case no new operations would be executed but the VM would continue as normal.
    50 // As only suitably privileged processes can open this process we concluded that
    51 // this wasn't worth worrying about.
    54 // forward reference
    55 class Win32AttachOperation;
    58 class Win32AttachListener: AllStatic {
    59  private:
    60   enum {
    61     preallocate_count = 4                   // number of preallocated operations
    62   };
    64   // protects the preallocated list and the operation list
    65   static HANDLE _mutex;
    67   // head of preallocated operations list
    68   static Win32AttachOperation* _avail;
    70   // head and tail of enqueue operations list
    71   static Win32AttachOperation* _head;
    72   static Win32AttachOperation* _tail;
    75   static Win32AttachOperation* head()                       { return _head; }
    76   static void set_head(Win32AttachOperation* head)          { _head = head; }
    78   static Win32AttachOperation* tail()                       { return _tail; }
    79   static void set_tail(Win32AttachOperation* tail)          { _tail = tail; }
    82   // used to wakeup the listener
    83   static HANDLE _wakeup;
    84   static HANDLE wakeup()                                    { return _wakeup; }
    86  public:
    87   enum {
    88     ATTACH_ERROR_DISABLED               = 100,              // error codes
    89     ATTACH_ERROR_RESOURCE               = 101,
    90     ATTACH_ERROR_ILLEGALARG             = 102,
    91     ATTACH_ERROR_INTERNAL               = 103
    92   };
    94   static int init();
    95   static HANDLE mutex()                                     { return _mutex; }
    97   static Win32AttachOperation* available()                  { return _avail; }
    98   static void set_available(Win32AttachOperation* avail)    { _avail = avail; }
   100   // enqueue an operation to the end of the list
   101   static int enqueue(char* cmd, char* arg1, char* arg2, char* arg3, char* pipename);
   103   // dequeue an operation from from head of the list
   104   static Win32AttachOperation* dequeue();
   105 };
   107 // statics
   108 HANDLE Win32AttachListener::_mutex;
   109 HANDLE Win32AttachListener::_wakeup;
   110 Win32AttachOperation* Win32AttachListener::_avail;
   111 Win32AttachOperation* Win32AttachListener::_head;
   112 Win32AttachOperation* Win32AttachListener::_tail;
   115 // Win32AttachOperation is an AttachOperation that additionally encapsulates the name
   116 // of a pipe which is used to send the operation reply/output to the client.
   117 // Win32AttachOperation can also be linked in a list.
   119 class Win32AttachOperation: public AttachOperation {
   120  private:
   121   friend class Win32AttachListener;
   123   enum {
   124     pipe_name_max = 256             // maximum pipe name
   125   };
   127   char _pipe[pipe_name_max+1];
   129   const char* pipe() const                              { return _pipe; }
   130   void set_pipe(const char* pipe) {
   131     assert(strlen(pipe) <= pipe_name_max, "execeds maximum length of pipe name");
   132     strcpy(_pipe, pipe);
   133   }
   135   HANDLE open_pipe();
   136   static BOOL write_pipe(HANDLE hPipe, char* buf, int len);
   138   Win32AttachOperation* _next;
   140   Win32AttachOperation* next() const                    { return _next; }
   141   void set_next(Win32AttachOperation* next)             { _next = next; }
   143   // noarg constructor as operation is preallocated
   144   Win32AttachOperation() : AttachOperation("<noname>") {
   145     set_pipe("<nopipe>");
   146     set_next(NULL);
   147   }
   149  public:
   150   void Win32AttachOperation::complete(jint result, bufferedStream* result_stream);
   151 };
   154 // preallocate the required number of operations
   155 int Win32AttachListener::init() {
   156   _mutex = (void*)::CreateMutex(NULL, FALSE, NULL);
   157   guarantee(_mutex != (HANDLE)NULL, "mutex creation failed");
   159   _wakeup = ::CreateSemaphore(NULL, 0, 1, NULL);
   160   guarantee(_wakeup != (HANDLE)NULL, "semaphore creation failed");
   162   set_head(NULL);
   163   set_tail(NULL);
   165   // preallocate a few operations
   166   set_available(NULL);
   167   for (int i=0; i<preallocate_count; i++) {
   168     Win32AttachOperation* op = new Win32AttachOperation();
   169     op->set_next(available());
   170     set_available(op);
   171   }
   173   return 0;
   174 }
   176 // Enqueue an operation. This is called from a native thread that is not attached to VM.
   177 // Also we need to be careful not to execute anything that results in more than a 4k stack.
   178 //
   179 int Win32AttachListener::enqueue(char* cmd, char* arg0, char* arg1, char* arg2, char* pipename) {
   180   // listener not running
   181   if (!AttachListener::is_initialized()) {
   182     return ATTACH_ERROR_DISABLED;
   183   }
   185   // check that all paramteres to the operation
   186   if (strlen(cmd) > AttachOperation::name_length_max) return ATTACH_ERROR_ILLEGALARG;
   187   if (strlen(arg0) > AttachOperation::arg_length_max) return ATTACH_ERROR_ILLEGALARG;
   188   if (strlen(arg0) > AttachOperation::arg_length_max) return ATTACH_ERROR_ILLEGALARG;
   189   if (strlen(pipename) > Win32AttachOperation::pipe_name_max) return ATTACH_ERROR_ILLEGALARG;
   191   // check for a well-formed pipename
   192   if (strstr(pipename, "\\\\.\\pipe\\") != pipename) return ATTACH_ERROR_ILLEGALARG;
   194   // grab the lock for the list
   195   DWORD res = ::WaitForSingleObject(mutex(), INFINITE);
   196   if (res != WAIT_OBJECT_0) {
   197     return ATTACH_ERROR_INTERNAL;
   198   }
   200   // try to get an operation from the available list
   201   Win32AttachOperation* op = available();
   202   if (op != NULL) {
   203     set_available(op->next());
   205     // add to end (tail) of list
   206     op->set_next(NULL);
   207     if (tail() == NULL) {
   208       set_head(op);
   209     } else {
   210       tail()->set_next(op);
   211     }
   212     set_tail(op);
   214     op->set_name(cmd);
   215     op->set_arg(0, arg0);
   216     op->set_arg(1, arg1);
   217     op->set_arg(2, arg2);
   218     op->set_pipe(pipename);
   220     // wakeup the thread waiting for operations
   221     ::ReleaseSemaphore(wakeup(), 1, NULL);
   222   }
   223   ::ReleaseMutex(mutex());
   225   return (op != NULL) ? 0 : ATTACH_ERROR_RESOURCE;
   226 }
   229 // dequeue the operation from the head of the operation list. If
   230 Win32AttachOperation* Win32AttachListener::dequeue() {
   231   for (;;) {
   232     DWORD res = ::WaitForSingleObject(wakeup(), INFINITE);
   233     guarantee(res == WAIT_OBJECT_0, "wait failed");
   235     res = ::WaitForSingleObject(mutex(), INFINITE);
   236     guarantee(res == WAIT_OBJECT_0, "wait failed");
   238     Win32AttachOperation* op = head();
   239     if (op != NULL) {
   240       set_head(op->next());
   241       if (head() == NULL) {     // list is empty
   242         set_tail(NULL);
   243       }
   244     }
   245     ::ReleaseMutex(mutex());
   247     if (op != NULL) {
   248       return op;
   249     }
   250   }
   251 }
   254 // open the pipe to the client
   255 HANDLE Win32AttachOperation::open_pipe() {
   256   HANDLE hPipe;
   258   hPipe = ::CreateFile( pipe(),  // pipe name
   259                         GENERIC_WRITE,   // write only
   260                         0,              // no sharing
   261                         NULL,           // default security attributes
   262                         OPEN_EXISTING,  // opens existing pipe
   263                         0,              // default attributes
   264                         NULL);          // no template file
   266   if (hPipe != INVALID_HANDLE_VALUE) {
   267     // shouldn't happen as there is a pipe created per operation
   268     if (::GetLastError() == ERROR_PIPE_BUSY) {
   269       return INVALID_HANDLE_VALUE;
   270     }
   271   }
   272   return hPipe;
   273 }
   275 // write to the pipe
   276 BOOL Win32AttachOperation::write_pipe(HANDLE hPipe, char* buf, int len) {
   277   do {
   278     DWORD nwrote;
   280     BOOL fSuccess = WriteFile(  hPipe,                  // pipe handle
   281                                 (LPCVOID)buf,           // message
   282                                 (DWORD)len,             // message length
   283                                 &nwrote,                // bytes written
   284                                 NULL);                  // not overlapped
   285     if (!fSuccess) {
   286       return fSuccess;
   287     }
   288     buf += nwrote;
   289     len -= nwrote;
   290   }
   291   while (len > 0);
   292   return TRUE;
   293 }
   295 // Complete the operation:
   296 //   - open the pipe to the client
   297 //   - write the operation result (a jint)
   298 //   - write the operation output (the result stream)
   299 //
   300 void Win32AttachOperation::complete(jint result, bufferedStream* result_stream) {
   301   JavaThread* thread = JavaThread::current();
   302   ThreadBlockInVM tbivm(thread);
   304   thread->set_suspend_equivalent();
   305   // cleared by handle_special_suspend_equivalent_condition() or
   306   // java_suspend_self() via check_and_wait_while_suspended()
   308   HANDLE hPipe = open_pipe();
   309   if (hPipe != INVALID_HANDLE_VALUE) {
   310     BOOL fSuccess;
   312     char msg[32];
   313     sprintf(msg, "%d\n", result);
   315     fSuccess = write_pipe(hPipe, msg, (int)strlen(msg));
   316     if (fSuccess) {
   317       write_pipe(hPipe, (char*) result_stream->base(), (int)(result_stream->size()));
   318     }
   320     // Need to flush buffers
   321     FlushFileBuffers(hPipe);
   322     CloseHandle(hPipe);
   323   }
   325   DWORD res = ::WaitForSingleObject(Win32AttachListener::mutex(), INFINITE);
   326   if (res == WAIT_OBJECT_0) {
   328     // put the operation back on the available list
   329     set_next(Win32AttachListener::available());
   330     Win32AttachListener::set_available(this);
   332     ::ReleaseMutex(Win32AttachListener::mutex());
   333   }
   335   // were we externally suspended while we were waiting?
   336   thread->check_and_wait_while_suspended();
   337 }
   340 // AttachOperation functions
   342 AttachOperation* AttachListener::dequeue() {
   343   JavaThread* thread = JavaThread::current();
   344   ThreadBlockInVM tbivm(thread);
   346   thread->set_suspend_equivalent();
   347   // cleared by handle_special_suspend_equivalent_condition() or
   348   // java_suspend_self() via check_and_wait_while_suspended()
   350   AttachOperation* op = Win32AttachListener::dequeue();
   352   // were we externally suspended while we were waiting?
   353   thread->check_and_wait_while_suspended();
   355   return op;
   356 }
   358 int AttachListener::pd_init() {
   359   return Win32AttachListener::init();
   360 }
   362 // always startup on Windows NT/2000/XP
   363 bool AttachListener::init_at_startup() {
   364   return os::win32::is_nt();
   365 }
   367 // no trigger mechanism on Windows to start Attach Listener lazily
   368 bool AttachListener::is_init_trigger() {
   369   return false;
   370 }
   372 void AttachListener::abort() {
   373   // nothing to do
   374 }
   376 void AttachListener::pd_data_dump() {
   377   os::signal_notify(SIGBREAK);
   378 }
   380 AttachOperationFunctionInfo* AttachListener::pd_find_operation(const char* n) {
   381   return NULL;
   382 }
   384 jint AttachListener::pd_set_flag(AttachOperation* op, outputStream* out) {
   385   out->print_cr("flag '%s' cannot be changed", op->arg(0));
   386   return JNI_ERR;
   387 }
   389 void AttachListener::pd_detachall() {
   390   // do nothing for now
   391 }
   393 // Native thread started by remote client executes this.
   394 extern "C" {
   395   JNIEXPORT jint JNICALL
   396     JVM_EnqueueOperation(char* cmd, char* arg0, char* arg1, char* arg2, char* pipename) {
   397       return (jint)Win32AttachListener::enqueue(cmd, arg0, arg1, arg2, pipename);
   398     }
   400 } // extern

mercurial