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