src/hotspot/os/windows/attachListener_windows.cpp
author coleenp
Fri, 16 Mar 2018 09:12:13 -0400
changeset 49449 ef5d5d343e2a
parent 47216 71c04702a3d5
child 49742 1196aa0be8be
permissions -rw-r--r--
8199263: Split interfaceSupport.hpp to not require including .inline.hpp files Summary: interfaceSupport.hpp is an inline file so moved to interfaceSupport.inline.hpp and stopped including it in .hpp files Reviewed-by: stefank, rehn, kvn
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"
49449
ef5d5d343e2a 8199263: Split interfaceSupport.hpp to not require including .inline.hpp files
coleenp
parents: 47216
diff changeset
    26
#include "runtime/interfaceSupport.inline.hpp"
7397
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
27471
6e56277909f1 8062370: Various minor code improvements
goetz
parents: 18931
diff changeset
    33
#include <stdio.h>
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
    34
489c9b5090e2 Initial load
duke
parents:
diff changeset
    35
// The AttachListener thread services a queue of operations. It blocks in the dequeue
489c9b5090e2 Initial load
duke
parents:
diff changeset
    36
// function until an operation is enqueued. A client enqueues an operation by creating
489c9b5090e2 Initial load
duke
parents:
diff changeset
    37
// a thread in this process using the Win32 CreateRemoteThread function. That thread
489c9b5090e2 Initial load
duke
parents:
diff changeset
    38
// executes a small stub generated by the client. The stub invokes the
489c9b5090e2 Initial load
duke
parents:
diff changeset
    39
// JVM_EnqueueOperation function which checks the operation parameters and enqueues
489c9b5090e2 Initial load
duke
parents:
diff changeset
    40
// the operation to the queue serviced by the attach listener. The thread created by
489c9b5090e2 Initial load
duke
parents:
diff changeset
    41
// the client is a native thread and is restricted to a single page of stack. To keep
489c9b5090e2 Initial load
duke
parents:
diff changeset
    42
// it simple operations are pre-allocated at initialization time. An enqueue thus
489c9b5090e2 Initial load
duke
parents:
diff changeset
    43
// takes a preallocated operation, populates the operation parameters, adds it to
489c9b5090e2 Initial load
duke
parents:
diff changeset
    44
// queue and wakes up the attach listener.
489c9b5090e2 Initial load
duke
parents:
diff changeset
    45
//
489c9b5090e2 Initial load
duke
parents:
diff changeset
    46
// When an operation has completed the attach listener is required to send the
489c9b5090e2 Initial load
duke
parents:
diff changeset
    47
// operation result and any result data to the client. In this implementation the
489c9b5090e2 Initial load
duke
parents:
diff changeset
    48
// client is a pipe server. In the enqueue operation it provides the name of pipe
489c9b5090e2 Initial load
duke
parents:
diff changeset
    49
// to this process. When the operation is completed this process opens the pipe and
489c9b5090e2 Initial load
duke
parents:
diff changeset
    50
// sends the result and output back to the client. Note that writing to the pipe
489c9b5090e2 Initial load
duke
parents:
diff changeset
    51
// (and flushing the output) is a blocking operation. This means that a non-responsive
489c9b5090e2 Initial load
duke
parents:
diff changeset
    52
// client could potentially hang the attach listener thread indefinitely. In that
489c9b5090e2 Initial load
duke
parents:
diff changeset
    53
// case no new operations would be executed but the VM would continue as normal.
489c9b5090e2 Initial load
duke
parents:
diff changeset
    54
// As only suitably privileged processes can open this process we concluded that
489c9b5090e2 Initial load
duke
parents:
diff changeset
    55
// this wasn't worth worrying about.
489c9b5090e2 Initial load
duke
parents:
diff changeset
    56
489c9b5090e2 Initial load
duke
parents:
diff changeset
    57
489c9b5090e2 Initial load
duke
parents:
diff changeset
    58
// forward reference
489c9b5090e2 Initial load
duke
parents:
diff changeset
    59
class Win32AttachOperation;
489c9b5090e2 Initial load
duke
parents:
diff changeset
    60
489c9b5090e2 Initial load
duke
parents:
diff changeset
    61
489c9b5090e2 Initial load
duke
parents:
diff changeset
    62
class Win32AttachListener: AllStatic {
489c9b5090e2 Initial load
duke
parents:
diff changeset
    63
 private:
489c9b5090e2 Initial load
duke
parents:
diff changeset
    64
  enum {
29322
1f646019dc45 8073042: jcmd hangs until another jcmd is executed (which, in turn also hangs)
mgronlun
parents: 27471
diff changeset
    65
    max_enqueued_operations = 4
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
    66
  };
489c9b5090e2 Initial load
duke
parents:
diff changeset
    67
489c9b5090e2 Initial load
duke
parents:
diff changeset
    68
  // protects the preallocated list and the operation list
489c9b5090e2 Initial load
duke
parents:
diff changeset
    69
  static HANDLE _mutex;
489c9b5090e2 Initial load
duke
parents:
diff changeset
    70
489c9b5090e2 Initial load
duke
parents:
diff changeset
    71
  // head of preallocated operations list
489c9b5090e2 Initial load
duke
parents:
diff changeset
    72
  static Win32AttachOperation* _avail;
489c9b5090e2 Initial load
duke
parents:
diff changeset
    73
489c9b5090e2 Initial load
duke
parents:
diff changeset
    74
  // head and tail of enqueue operations list
489c9b5090e2 Initial load
duke
parents:
diff changeset
    75
  static Win32AttachOperation* _head;
489c9b5090e2 Initial load
duke
parents:
diff changeset
    76
  static Win32AttachOperation* _tail;
489c9b5090e2 Initial load
duke
parents:
diff changeset
    77
489c9b5090e2 Initial load
duke
parents:
diff changeset
    78
489c9b5090e2 Initial load
duke
parents:
diff changeset
    79
  static Win32AttachOperation* head()                       { return _head; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
    80
  static void set_head(Win32AttachOperation* head)          { _head = head; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
    81
489c9b5090e2 Initial load
duke
parents:
diff changeset
    82
  static Win32AttachOperation* tail()                       { return _tail; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
    83
  static void set_tail(Win32AttachOperation* tail)          { _tail = tail; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
    84
489c9b5090e2 Initial load
duke
parents:
diff changeset
    85
29322
1f646019dc45 8073042: jcmd hangs until another jcmd is executed (which, in turn also hangs)
mgronlun
parents: 27471
diff changeset
    86
  // A semaphore is used for communication about enqueued operations.
1f646019dc45 8073042: jcmd hangs until another jcmd is executed (which, in turn also hangs)
mgronlun
parents: 27471
diff changeset
    87
  // The maximum count for the semaphore object will be set to "max_enqueued_operations".
1f646019dc45 8073042: jcmd hangs until another jcmd is executed (which, in turn also hangs)
mgronlun
parents: 27471
diff changeset
    88
  // The state of a semaphore is signaled when its count is greater than
1f646019dc45 8073042: jcmd hangs until another jcmd is executed (which, in turn also hangs)
mgronlun
parents: 27471
diff changeset
    89
  // zero (there are operations enqueued), and nonsignaled when it is zero.
1f646019dc45 8073042: jcmd hangs until another jcmd is executed (which, in turn also hangs)
mgronlun
parents: 27471
diff changeset
    90
  static HANDLE _enqueued_ops_semaphore;
1f646019dc45 8073042: jcmd hangs until another jcmd is executed (which, in turn also hangs)
mgronlun
parents: 27471
diff changeset
    91
  static HANDLE enqueued_ops_semaphore() { return _enqueued_ops_semaphore; }
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
    92
489c9b5090e2 Initial load
duke
parents:
diff changeset
    93
 public:
489c9b5090e2 Initial load
duke
parents:
diff changeset
    94
  enum {
489c9b5090e2 Initial load
duke
parents:
diff changeset
    95
    ATTACH_ERROR_DISABLED               = 100,              // error codes
489c9b5090e2 Initial load
duke
parents:
diff changeset
    96
    ATTACH_ERROR_RESOURCE               = 101,
489c9b5090e2 Initial load
duke
parents:
diff changeset
    97
    ATTACH_ERROR_ILLEGALARG             = 102,
489c9b5090e2 Initial load
duke
parents:
diff changeset
    98
    ATTACH_ERROR_INTERNAL               = 103
489c9b5090e2 Initial load
duke
parents:
diff changeset
    99
  };
489c9b5090e2 Initial load
duke
parents:
diff changeset
   100
489c9b5090e2 Initial load
duke
parents:
diff changeset
   101
  static int init();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   102
  static HANDLE mutex()                                     { return _mutex; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   103
489c9b5090e2 Initial load
duke
parents:
diff changeset
   104
  static Win32AttachOperation* available()                  { return _avail; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   105
  static void set_available(Win32AttachOperation* avail)    { _avail = avail; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   106
489c9b5090e2 Initial load
duke
parents:
diff changeset
   107
  // enqueue an operation to the end of the list
489c9b5090e2 Initial load
duke
parents:
diff changeset
   108
  static int enqueue(char* cmd, char* arg1, char* arg2, char* arg3, char* pipename);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   109
489c9b5090e2 Initial load
duke
parents:
diff changeset
   110
  // dequeue an operation from from head of the list
489c9b5090e2 Initial load
duke
parents:
diff changeset
   111
  static Win32AttachOperation* dequeue();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   112
};
489c9b5090e2 Initial load
duke
parents:
diff changeset
   113
489c9b5090e2 Initial load
duke
parents:
diff changeset
   114
// statics
489c9b5090e2 Initial load
duke
parents:
diff changeset
   115
HANDLE Win32AttachListener::_mutex;
29322
1f646019dc45 8073042: jcmd hangs until another jcmd is executed (which, in turn also hangs)
mgronlun
parents: 27471
diff changeset
   116
HANDLE Win32AttachListener::_enqueued_ops_semaphore;
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   117
Win32AttachOperation* Win32AttachListener::_avail;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   118
Win32AttachOperation* Win32AttachListener::_head;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   119
Win32AttachOperation* Win32AttachListener::_tail;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   120
489c9b5090e2 Initial load
duke
parents:
diff changeset
   121
489c9b5090e2 Initial load
duke
parents:
diff changeset
   122
// Win32AttachOperation is an AttachOperation that additionally encapsulates the name
489c9b5090e2 Initial load
duke
parents:
diff changeset
   123
// of a pipe which is used to send the operation reply/output to the client.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   124
// Win32AttachOperation can also be linked in a list.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   125
489c9b5090e2 Initial load
duke
parents:
diff changeset
   126
class Win32AttachOperation: public AttachOperation {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   127
 private:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   128
  friend class Win32AttachListener;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   129
489c9b5090e2 Initial load
duke
parents:
diff changeset
   130
  enum {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   131
    pipe_name_max = 256             // maximum pipe name
489c9b5090e2 Initial load
duke
parents:
diff changeset
   132
  };
489c9b5090e2 Initial load
duke
parents:
diff changeset
   133
489c9b5090e2 Initial load
duke
parents:
diff changeset
   134
  char _pipe[pipe_name_max+1];
489c9b5090e2 Initial load
duke
parents:
diff changeset
   135
489c9b5090e2 Initial load
duke
parents:
diff changeset
   136
  const char* pipe() const                              { return _pipe; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   137
  void set_pipe(const char* pipe) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   138
    assert(strlen(pipe) <= pipe_name_max, "execeds maximum length of pipe name");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   139
    strcpy(_pipe, pipe);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   140
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   141
489c9b5090e2 Initial load
duke
parents:
diff changeset
   142
  HANDLE open_pipe();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   143
  static BOOL write_pipe(HANDLE hPipe, char* buf, int len);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   144
489c9b5090e2 Initial load
duke
parents:
diff changeset
   145
  Win32AttachOperation* _next;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   146
489c9b5090e2 Initial load
duke
parents:
diff changeset
   147
  Win32AttachOperation* next() const                    { return _next; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   148
  void set_next(Win32AttachOperation* next)             { _next = next; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   149
489c9b5090e2 Initial load
duke
parents:
diff changeset
   150
  // noarg constructor as operation is preallocated
489c9b5090e2 Initial load
duke
parents:
diff changeset
   151
  Win32AttachOperation() : AttachOperation("<noname>") {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   152
    set_pipe("<nopipe>");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   153
    set_next(NULL);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   154
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   155
489c9b5090e2 Initial load
duke
parents:
diff changeset
   156
 public:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   157
  void Win32AttachOperation::complete(jint result, bufferedStream* result_stream);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   158
};
489c9b5090e2 Initial load
duke
parents:
diff changeset
   159
489c9b5090e2 Initial load
duke
parents:
diff changeset
   160
29322
1f646019dc45 8073042: jcmd hangs until another jcmd is executed (which, in turn also hangs)
mgronlun
parents: 27471
diff changeset
   161
// Preallocate the maximum number of operations that can be enqueued.
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   162
int Win32AttachListener::init() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   163
  _mutex = (void*)::CreateMutex(NULL, FALSE, NULL);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   164
  guarantee(_mutex != (HANDLE)NULL, "mutex creation failed");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   165
29322
1f646019dc45 8073042: jcmd hangs until another jcmd is executed (which, in turn also hangs)
mgronlun
parents: 27471
diff changeset
   166
  _enqueued_ops_semaphore = ::CreateSemaphore(NULL, 0, max_enqueued_operations, NULL);
1f646019dc45 8073042: jcmd hangs until another jcmd is executed (which, in turn also hangs)
mgronlun
parents: 27471
diff changeset
   167
  guarantee(_enqueued_ops_semaphore != (HANDLE)NULL, "semaphore creation failed");
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   168
489c9b5090e2 Initial load
duke
parents:
diff changeset
   169
  set_head(NULL);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   170
  set_tail(NULL);
29322
1f646019dc45 8073042: jcmd hangs until another jcmd is executed (which, in turn also hangs)
mgronlun
parents: 27471
diff changeset
   171
  set_available(NULL);
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   172
29322
1f646019dc45 8073042: jcmd hangs until another jcmd is executed (which, in turn also hangs)
mgronlun
parents: 27471
diff changeset
   173
  for (int i=0; i<max_enqueued_operations; i++) {
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   174
    Win32AttachOperation* op = new Win32AttachOperation();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   175
    op->set_next(available());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   176
    set_available(op);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   177
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   178
489c9b5090e2 Initial load
duke
parents:
diff changeset
   179
  return 0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   180
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   181
489c9b5090e2 Initial load
duke
parents:
diff changeset
   182
// Enqueue an operation. This is called from a native thread that is not attached to VM.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   183
// 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
   184
//
489c9b5090e2 Initial load
duke
parents:
diff changeset
   185
int Win32AttachListener::enqueue(char* cmd, char* arg0, char* arg1, char* arg2, char* pipename) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   186
  // listener not running
489c9b5090e2 Initial load
duke
parents:
diff changeset
   187
  if (!AttachListener::is_initialized()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   188
    return ATTACH_ERROR_DISABLED;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   189
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   190
489c9b5090e2 Initial load
duke
parents:
diff changeset
   191
  // check that all paramteres to the operation
489c9b5090e2 Initial load
duke
parents:
diff changeset
   192
  if (strlen(cmd) > AttachOperation::name_length_max) return ATTACH_ERROR_ILLEGALARG;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   193
  if (strlen(arg0) > AttachOperation::arg_length_max) return ATTACH_ERROR_ILLEGALARG;
33794
41ef3dc95179 8140482: Various minor code improvements (runtime)
goetz
parents: 29322
diff changeset
   194
  if (strlen(arg1) > AttachOperation::arg_length_max) return ATTACH_ERROR_ILLEGALARG;
41ef3dc95179 8140482: Various minor code improvements (runtime)
goetz
parents: 29322
diff changeset
   195
  if (strlen(arg2) > AttachOperation::arg_length_max) return ATTACH_ERROR_ILLEGALARG;
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   196
  if (strlen(pipename) > Win32AttachOperation::pipe_name_max) return ATTACH_ERROR_ILLEGALARG;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   197
489c9b5090e2 Initial load
duke
parents:
diff changeset
   198
  // check for a well-formed pipename
489c9b5090e2 Initial load
duke
parents:
diff changeset
   199
  if (strstr(pipename, "\\\\.\\pipe\\") != pipename) return ATTACH_ERROR_ILLEGALARG;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   200
489c9b5090e2 Initial load
duke
parents:
diff changeset
   201
  // grab the lock for the list
489c9b5090e2 Initial load
duke
parents:
diff changeset
   202
  DWORD res = ::WaitForSingleObject(mutex(), INFINITE);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   203
  if (res != WAIT_OBJECT_0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   204
    return ATTACH_ERROR_INTERNAL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   205
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   206
489c9b5090e2 Initial load
duke
parents:
diff changeset
   207
  // try to get an operation from the available list
489c9b5090e2 Initial load
duke
parents:
diff changeset
   208
  Win32AttachOperation* op = available();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   209
  if (op != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   210
    set_available(op->next());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   211
489c9b5090e2 Initial load
duke
parents:
diff changeset
   212
    // add to end (tail) of list
489c9b5090e2 Initial load
duke
parents:
diff changeset
   213
    op->set_next(NULL);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   214
    if (tail() == NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   215
      set_head(op);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   216
    } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   217
      tail()->set_next(op);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   218
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   219
    set_tail(op);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   220
489c9b5090e2 Initial load
duke
parents:
diff changeset
   221
    op->set_name(cmd);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   222
    op->set_arg(0, arg0);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   223
    op->set_arg(1, arg1);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   224
    op->set_arg(2, arg2);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   225
    op->set_pipe(pipename);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   226
29322
1f646019dc45 8073042: jcmd hangs until another jcmd is executed (which, in turn also hangs)
mgronlun
parents: 27471
diff changeset
   227
    // Increment number of enqueued operations.
1f646019dc45 8073042: jcmd hangs until another jcmd is executed (which, in turn also hangs)
mgronlun
parents: 27471
diff changeset
   228
    // Side effect: Semaphore will be signaled and will release
1f646019dc45 8073042: jcmd hangs until another jcmd is executed (which, in turn also hangs)
mgronlun
parents: 27471
diff changeset
   229
    // any blocking waiters (i.e. the AttachListener thread).
1f646019dc45 8073042: jcmd hangs until another jcmd is executed (which, in turn also hangs)
mgronlun
parents: 27471
diff changeset
   230
    BOOL not_exceeding_semaphore_maximum_count =
1f646019dc45 8073042: jcmd hangs until another jcmd is executed (which, in turn also hangs)
mgronlun
parents: 27471
diff changeset
   231
      ::ReleaseSemaphore(enqueued_ops_semaphore(), 1, NULL);
1f646019dc45 8073042: jcmd hangs until another jcmd is executed (which, in turn also hangs)
mgronlun
parents: 27471
diff changeset
   232
    guarantee(not_exceeding_semaphore_maximum_count, "invariant");
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   233
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   234
  ::ReleaseMutex(mutex());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   235
489c9b5090e2 Initial load
duke
parents:
diff changeset
   236
  return (op != NULL) ? 0 : ATTACH_ERROR_RESOURCE;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   237
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   238
489c9b5090e2 Initial load
duke
parents:
diff changeset
   239
29322
1f646019dc45 8073042: jcmd hangs until another jcmd is executed (which, in turn also hangs)
mgronlun
parents: 27471
diff changeset
   240
// dequeue the operation from the head of the operation list.
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   241
Win32AttachOperation* Win32AttachListener::dequeue() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   242
  for (;;) {
29322
1f646019dc45 8073042: jcmd hangs until another jcmd is executed (which, in turn also hangs)
mgronlun
parents: 27471
diff changeset
   243
    DWORD res = ::WaitForSingleObject(enqueued_ops_semaphore(), INFINITE);
1f646019dc45 8073042: jcmd hangs until another jcmd is executed (which, in turn also hangs)
mgronlun
parents: 27471
diff changeset
   244
    // returning from WaitForSingleObject will have decreased
1f646019dc45 8073042: jcmd hangs until another jcmd is executed (which, in turn also hangs)
mgronlun
parents: 27471
diff changeset
   245
    // the current count of the semaphore by 1.
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   246
    guarantee(res == WAIT_OBJECT_0, "wait failed");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   247
489c9b5090e2 Initial load
duke
parents:
diff changeset
   248
    res = ::WaitForSingleObject(mutex(), INFINITE);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   249
    guarantee(res == WAIT_OBJECT_0, "wait failed");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   250
489c9b5090e2 Initial load
duke
parents:
diff changeset
   251
    Win32AttachOperation* op = head();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   252
    if (op != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   253
      set_head(op->next());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   254
      if (head() == NULL) {     // list is empty
489c9b5090e2 Initial load
duke
parents:
diff changeset
   255
        set_tail(NULL);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   256
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   257
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   258
    ::ReleaseMutex(mutex());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   259
489c9b5090e2 Initial load
duke
parents:
diff changeset
   260
    if (op != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   261
      return op;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   262
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   263
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   264
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   265
489c9b5090e2 Initial load
duke
parents:
diff changeset
   266
489c9b5090e2 Initial load
duke
parents:
diff changeset
   267
// open the pipe to the client
489c9b5090e2 Initial load
duke
parents:
diff changeset
   268
HANDLE Win32AttachOperation::open_pipe() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   269
  HANDLE hPipe;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   270
489c9b5090e2 Initial load
duke
parents:
diff changeset
   271
  hPipe = ::CreateFile( pipe(),  // pipe name
489c9b5090e2 Initial load
duke
parents:
diff changeset
   272
                        GENERIC_WRITE,   // write only
489c9b5090e2 Initial load
duke
parents:
diff changeset
   273
                        0,              // no sharing
489c9b5090e2 Initial load
duke
parents:
diff changeset
   274
                        NULL,           // default security attributes
489c9b5090e2 Initial load
duke
parents:
diff changeset
   275
                        OPEN_EXISTING,  // opens existing pipe
489c9b5090e2 Initial load
duke
parents:
diff changeset
   276
                        0,              // default attributes
489c9b5090e2 Initial load
duke
parents:
diff changeset
   277
                        NULL);          // no template file
489c9b5090e2 Initial load
duke
parents:
diff changeset
   278
489c9b5090e2 Initial load
duke
parents:
diff changeset
   279
  if (hPipe != INVALID_HANDLE_VALUE) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   280
    // shouldn't happen as there is a pipe created per operation
489c9b5090e2 Initial load
duke
parents:
diff changeset
   281
    if (::GetLastError() == ERROR_PIPE_BUSY) {
27471
6e56277909f1 8062370: Various minor code improvements
goetz
parents: 18931
diff changeset
   282
      ::CloseHandle(hPipe);
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   283
      return INVALID_HANDLE_VALUE;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   284
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   285
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   286
  return hPipe;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   287
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   288
489c9b5090e2 Initial load
duke
parents:
diff changeset
   289
// write to the pipe
489c9b5090e2 Initial load
duke
parents:
diff changeset
   290
BOOL Win32AttachOperation::write_pipe(HANDLE hPipe, char* buf, int len) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   291
  do {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   292
    DWORD nwrote;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   293
489c9b5090e2 Initial load
duke
parents:
diff changeset
   294
    BOOL fSuccess = WriteFile(  hPipe,                  // pipe handle
489c9b5090e2 Initial load
duke
parents:
diff changeset
   295
                                (LPCVOID)buf,           // message
489c9b5090e2 Initial load
duke
parents:
diff changeset
   296
                                (DWORD)len,             // message length
489c9b5090e2 Initial load
duke
parents:
diff changeset
   297
                                &nwrote,                // bytes written
489c9b5090e2 Initial load
duke
parents:
diff changeset
   298
                                NULL);                  // not overlapped
489c9b5090e2 Initial load
duke
parents:
diff changeset
   299
    if (!fSuccess) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   300
      return fSuccess;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   301
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   302
    buf += nwrote;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   303
    len -= nwrote;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   304
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   305
  while (len > 0);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   306
  return TRUE;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   307
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   308
489c9b5090e2 Initial load
duke
parents:
diff changeset
   309
// Complete the operation:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   310
//   - open the pipe to the client
489c9b5090e2 Initial load
duke
parents:
diff changeset
   311
//   - write the operation result (a jint)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   312
//   - write the operation output (the result stream)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   313
//
489c9b5090e2 Initial load
duke
parents:
diff changeset
   314
void Win32AttachOperation::complete(jint result, bufferedStream* result_stream) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   315
  JavaThread* thread = JavaThread::current();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   316
  ThreadBlockInVM tbivm(thread);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   317
489c9b5090e2 Initial load
duke
parents:
diff changeset
   318
  thread->set_suspend_equivalent();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   319
  // cleared by handle_special_suspend_equivalent_condition() or
489c9b5090e2 Initial load
duke
parents:
diff changeset
   320
  // java_suspend_self() via check_and_wait_while_suspended()
489c9b5090e2 Initial load
duke
parents:
diff changeset
   321
489c9b5090e2 Initial load
duke
parents:
diff changeset
   322
  HANDLE hPipe = open_pipe();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   323
  if (hPipe != INVALID_HANDLE_VALUE) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   324
    BOOL fSuccess;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   325
489c9b5090e2 Initial load
duke
parents:
diff changeset
   326
    char msg[32];
27471
6e56277909f1 8062370: Various minor code improvements
goetz
parents: 18931
diff changeset
   327
    _snprintf(msg, sizeof(msg), "%d\n", result);
6e56277909f1 8062370: Various minor code improvements
goetz
parents: 18931
diff changeset
   328
    msg[sizeof(msg) - 1] = '\0';
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   329
489c9b5090e2 Initial load
duke
parents:
diff changeset
   330
    fSuccess = write_pipe(hPipe, msg, (int)strlen(msg));
489c9b5090e2 Initial load
duke
parents:
diff changeset
   331
    if (fSuccess) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   332
      write_pipe(hPipe, (char*) result_stream->base(), (int)(result_stream->size()));
489c9b5090e2 Initial load
duke
parents:
diff changeset
   333
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   334
489c9b5090e2 Initial load
duke
parents:
diff changeset
   335
    // Need to flush buffers
489c9b5090e2 Initial load
duke
parents:
diff changeset
   336
    FlushFileBuffers(hPipe);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   337
    CloseHandle(hPipe);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   338
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   339
489c9b5090e2 Initial load
duke
parents:
diff changeset
   340
  DWORD res = ::WaitForSingleObject(Win32AttachListener::mutex(), INFINITE);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   341
  if (res == WAIT_OBJECT_0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   342
489c9b5090e2 Initial load
duke
parents:
diff changeset
   343
    // put the operation back on the available list
489c9b5090e2 Initial load
duke
parents:
diff changeset
   344
    set_next(Win32AttachListener::available());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   345
    Win32AttachListener::set_available(this);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   346
489c9b5090e2 Initial load
duke
parents:
diff changeset
   347
    ::ReleaseMutex(Win32AttachListener::mutex());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   348
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   349
489c9b5090e2 Initial load
duke
parents:
diff changeset
   350
  // were we externally suspended while we were waiting?
489c9b5090e2 Initial load
duke
parents:
diff changeset
   351
  thread->check_and_wait_while_suspended();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   352
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   353
489c9b5090e2 Initial load
duke
parents:
diff changeset
   354
489c9b5090e2 Initial load
duke
parents:
diff changeset
   355
// AttachOperation functions
489c9b5090e2 Initial load
duke
parents:
diff changeset
   356
489c9b5090e2 Initial load
duke
parents:
diff changeset
   357
AttachOperation* AttachListener::dequeue() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   358
  JavaThread* thread = JavaThread::current();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   359
  ThreadBlockInVM tbivm(thread);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   360
489c9b5090e2 Initial load
duke
parents:
diff changeset
   361
  thread->set_suspend_equivalent();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   362
  // cleared by handle_special_suspend_equivalent_condition() or
489c9b5090e2 Initial load
duke
parents:
diff changeset
   363
  // java_suspend_self() via check_and_wait_while_suspended()
489c9b5090e2 Initial load
duke
parents:
diff changeset
   364
489c9b5090e2 Initial load
duke
parents:
diff changeset
   365
  AttachOperation* op = Win32AttachListener::dequeue();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   366
489c9b5090e2 Initial load
duke
parents:
diff changeset
   367
  // were we externally suspended while we were waiting?
489c9b5090e2 Initial load
duke
parents:
diff changeset
   368
  thread->check_and_wait_while_suspended();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   369
489c9b5090e2 Initial load
duke
parents:
diff changeset
   370
  return op;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   371
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   372
18931
5de3638104b4 7162400: Intermittent java.io.IOException: Bad file number during HotSpotVirtualMachine.executeCommand
allwin
parents: 7397
diff changeset
   373
void AttachListener::vm_start() {
5de3638104b4 7162400: Intermittent java.io.IOException: Bad file number during HotSpotVirtualMachine.executeCommand
allwin
parents: 7397
diff changeset
   374
  // nothing to do
5de3638104b4 7162400: Intermittent java.io.IOException: Bad file number during HotSpotVirtualMachine.executeCommand
allwin
parents: 7397
diff changeset
   375
}
5de3638104b4 7162400: Intermittent java.io.IOException: Bad file number during HotSpotVirtualMachine.executeCommand
allwin
parents: 7397
diff changeset
   376
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   377
int AttachListener::pd_init() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   378
  return Win32AttachListener::init();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   379
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   380
489c9b5090e2 Initial load
duke
parents:
diff changeset
   381
bool AttachListener::init_at_startup() {
35212
7a6d0993a080 8048521: Remove obsolete code from os_windows.cpp/hpp
ctornqvi
parents: 33794
diff changeset
   382
  return true;
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   383
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   384
489c9b5090e2 Initial load
duke
parents:
diff changeset
   385
// no trigger mechanism on Windows to start Attach Listener lazily
489c9b5090e2 Initial load
duke
parents:
diff changeset
   386
bool AttachListener::is_init_trigger() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   387
  return false;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   388
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   389
489c9b5090e2 Initial load
duke
parents:
diff changeset
   390
void AttachListener::abort() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   391
  // nothing to do
489c9b5090e2 Initial load
duke
parents:
diff changeset
   392
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   393
489c9b5090e2 Initial load
duke
parents:
diff changeset
   394
void AttachListener::pd_data_dump() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   395
  os::signal_notify(SIGBREAK);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   396
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   397
489c9b5090e2 Initial load
duke
parents:
diff changeset
   398
AttachOperationFunctionInfo* AttachListener::pd_find_operation(const char* n) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   399
  return NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   400
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   401
489c9b5090e2 Initial load
duke
parents:
diff changeset
   402
jint AttachListener::pd_set_flag(AttachOperation* op, outputStream* out) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   403
  out->print_cr("flag '%s' cannot be changed", op->arg(0));
489c9b5090e2 Initial load
duke
parents:
diff changeset
   404
  return JNI_ERR;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   405
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   406
489c9b5090e2 Initial load
duke
parents:
diff changeset
   407
void AttachListener::pd_detachall() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   408
  // do nothing for now
489c9b5090e2 Initial load
duke
parents:
diff changeset
   409
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   410
489c9b5090e2 Initial load
duke
parents:
diff changeset
   411
// Native thread started by remote client executes this.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   412
extern "C" {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   413
  JNIEXPORT jint JNICALL
489c9b5090e2 Initial load
duke
parents:
diff changeset
   414
    JVM_EnqueueOperation(char* cmd, char* arg0, char* arg1, char* arg2, char* pipename) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   415
      return (jint)Win32AttachListener::enqueue(cmd, arg0, arg1, arg2, pipename);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   416
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   417
489c9b5090e2 Initial load
duke
parents:
diff changeset
   418
} // extern