attachListener_windows.cpp revision 1472:c18cbe5936b8
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 */
24
25# include "incls/_precompiled.incl"
26# include "incls/_attachListener_windows.cpp.incl"
27
28#include <windows.h>
29#include <signal.h>             // SIGBREAK
30
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.
52
53
54// forward reference
55class Win32AttachOperation;
56
57
58class Win32AttachListener: AllStatic {
59 private:
60  enum {
61    preallocate_count = 4                   // number of preallocated operations
62  };
63
64  // protects the preallocated list and the operation list
65  static HANDLE _mutex;
66
67  // head of preallocated operations list
68  static Win32AttachOperation* _avail;
69
70  // head and tail of enqueue operations list
71  static Win32AttachOperation* _head;
72  static Win32AttachOperation* _tail;
73
74
75  static Win32AttachOperation* head()                       { return _head; }
76  static void set_head(Win32AttachOperation* head)          { _head = head; }
77
78  static Win32AttachOperation* tail()                       { return _tail; }
79  static void set_tail(Win32AttachOperation* tail)          { _tail = tail; }
80
81
82  // used to wakeup the listener
83  static HANDLE _wakeup;
84  static HANDLE wakeup()                                    { return _wakeup; }
85
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  };
93
94  static int init();
95  static HANDLE mutex()                                     { return _mutex; }
96
97  static Win32AttachOperation* available()                  { return _avail; }
98  static void set_available(Win32AttachOperation* avail)    { _avail = avail; }
99
100  // enqueue an operation to the end of the list
101  static int enqueue(char* cmd, char* arg1, char* arg2, char* arg3, char* pipename);
102
103  // dequeue an operation from from head of the list
104  static Win32AttachOperation* dequeue();
105};
106
107// statics
108HANDLE Win32AttachListener::_mutex;
109HANDLE Win32AttachListener::_wakeup;
110Win32AttachOperation* Win32AttachListener::_avail;
111Win32AttachOperation* Win32AttachListener::_head;
112Win32AttachOperation* Win32AttachListener::_tail;
113
114
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.
118
119class Win32AttachOperation: public AttachOperation {
120 private:
121  friend class Win32AttachListener;
122
123  enum {
124    pipe_name_max = 256             // maximum pipe name
125  };
126
127  char _pipe[pipe_name_max+1];
128
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  }
134
135  HANDLE open_pipe();
136  static BOOL write_pipe(HANDLE hPipe, char* buf, int len);
137
138  Win32AttachOperation* _next;
139
140  Win32AttachOperation* next() const                    { return _next; }
141  void set_next(Win32AttachOperation* next)             { _next = next; }
142
143  // noarg constructor as operation is preallocated
144  Win32AttachOperation() : AttachOperation("<noname>") {
145    set_pipe("<nopipe>");
146    set_next(NULL);
147  }
148
149 public:
150  void Win32AttachOperation::complete(jint result, bufferedStream* result_stream);
151};
152
153
154// preallocate the required number of operations
155int Win32AttachListener::init() {
156  _mutex = (void*)::CreateMutex(NULL, FALSE, NULL);
157  guarantee(_mutex != (HANDLE)NULL, "mutex creation failed");
158
159  _wakeup = ::CreateSemaphore(NULL, 0, 1, NULL);
160  guarantee(_wakeup != (HANDLE)NULL, "semaphore creation failed");
161
162  set_head(NULL);
163  set_tail(NULL);
164
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  }
172
173  return 0;
174}
175
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//
179int 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  }
184
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;
190
191  // check for a well-formed pipename
192  if (strstr(pipename, "\\\\.\\pipe\\") != pipename) return ATTACH_ERROR_ILLEGALARG;
193
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  }
199
200  // try to get an operation from the available list
201  Win32AttachOperation* op = available();
202  if (op != NULL) {
203    set_available(op->next());
204
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);
213
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);
219
220    // wakeup the thread waiting for operations
221    ::ReleaseSemaphore(wakeup(), 1, NULL);
222  }
223  ::ReleaseMutex(mutex());
224
225  return (op != NULL) ? 0 : ATTACH_ERROR_RESOURCE;
226}
227
228
229// dequeue the operation from the head of the operation list. If
230Win32AttachOperation* Win32AttachListener::dequeue() {
231  for (;;) {
232    DWORD res = ::WaitForSingleObject(wakeup(), INFINITE);
233    guarantee(res == WAIT_OBJECT_0, "wait failed");
234
235    res = ::WaitForSingleObject(mutex(), INFINITE);
236    guarantee(res == WAIT_OBJECT_0, "wait failed");
237
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());
246
247    if (op != NULL) {
248      return op;
249    }
250  }
251}
252
253
254// open the pipe to the client
255HANDLE Win32AttachOperation::open_pipe() {
256  HANDLE hPipe;
257
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
265
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}
274
275// write to the pipe
276BOOL Win32AttachOperation::write_pipe(HANDLE hPipe, char* buf, int len) {
277  do {
278    DWORD nwrote;
279
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}
294
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//
300void Win32AttachOperation::complete(jint result, bufferedStream* result_stream) {
301  JavaThread* thread = JavaThread::current();
302  ThreadBlockInVM tbivm(thread);
303
304  thread->set_suspend_equivalent();
305  // cleared by handle_special_suspend_equivalent_condition() or
306  // java_suspend_self() via check_and_wait_while_suspended()
307
308  HANDLE hPipe = open_pipe();
309  if (hPipe != INVALID_HANDLE_VALUE) {
310    BOOL fSuccess;
311
312    char msg[32];
313    sprintf(msg, "%d\n", result);
314
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    }
319
320    // Need to flush buffers
321    FlushFileBuffers(hPipe);
322    CloseHandle(hPipe);
323  }
324
325  DWORD res = ::WaitForSingleObject(Win32AttachListener::mutex(), INFINITE);
326  if (res == WAIT_OBJECT_0) {
327
328    // put the operation back on the available list
329    set_next(Win32AttachListener::available());
330    Win32AttachListener::set_available(this);
331
332    ::ReleaseMutex(Win32AttachListener::mutex());
333  }
334
335  // were we externally suspended while we were waiting?
336  thread->check_and_wait_while_suspended();
337}
338
339
340// AttachOperation functions
341
342AttachOperation* AttachListener::dequeue() {
343  JavaThread* thread = JavaThread::current();
344  ThreadBlockInVM tbivm(thread);
345
346  thread->set_suspend_equivalent();
347  // cleared by handle_special_suspend_equivalent_condition() or
348  // java_suspend_self() via check_and_wait_while_suspended()
349
350  AttachOperation* op = Win32AttachListener::dequeue();
351
352  // were we externally suspended while we were waiting?
353  thread->check_and_wait_while_suspended();
354
355  return op;
356}
357
358int AttachListener::pd_init() {
359  return Win32AttachListener::init();
360}
361
362// always startup on Windows NT/2000/XP
363bool AttachListener::init_at_startup() {
364  return os::win32::is_nt();
365}
366
367// no trigger mechanism on Windows to start Attach Listener lazily
368bool AttachListener::is_init_trigger() {
369  return false;
370}
371
372void AttachListener::abort() {
373  // nothing to do
374}
375
376void AttachListener::pd_data_dump() {
377  os::signal_notify(SIGBREAK);
378}
379
380AttachOperationFunctionInfo* AttachListener::pd_find_operation(const char* n) {
381  return NULL;
382}
383
384jint 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}
388
389void AttachListener::pd_detachall() {
390  // do nothing for now
391}
392
393// Native thread started by remote client executes this.
394extern "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    }
399
400} // extern
401