attachListener_windows.cpp revision 1879:f95d63e2154a
192108Sphk/* 292108Sphk * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. 392108Sphk * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 492108Sphk * 592108Sphk * This code is free software; you can redistribute it and/or modify it 692108Sphk * under the terms of the GNU General Public License version 2 only, as 792108Sphk * published by the Free Software Foundation. 892108Sphk * 992108Sphk * This code is distributed in the hope that it will be useful, but WITHOUT 1092108Sphk * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1192108Sphk * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1292108Sphk * version 2 for more details (a copy is included in the LICENSE file that 1392108Sphk * accompanied this code). 1492108Sphk * 1592108Sphk * You should have received a copy of the GNU General Public License version 1692108Sphk * 2 along with this work; if not, write to the Free Software Foundation, 1792108Sphk * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 1892108Sphk * 1992108Sphk * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 2092108Sphk * or visit www.oracle.com if you need additional information or have any 2192108Sphk * questions. 2292108Sphk * 2392108Sphk */ 2492108Sphk 2592108Sphk#include "precompiled.hpp" 2692108Sphk#include "runtime/interfaceSupport.hpp" 2792108Sphk#include "runtime/os.hpp" 2892108Sphk#include "services/attachListener.hpp" 2992108Sphk#include "services/dtraceAttacher.hpp" 3092108Sphk 3192108Sphk#include <windows.h> 3292108Sphk#include <signal.h> // SIGBREAK 3392108Sphk 3492108Sphk// The AttachListener thread services a queue of operations. It blocks in the dequeue 3592108Sphk// function until an operation is enqueued. A client enqueues an operation by creating 3692108Sphk// a thread in this process using the Win32 CreateRemoteThread function. That thread 3792108Sphk// executes a small stub generated by the client. The stub invokes the 3892108Sphk// JVM_EnqueueOperation function which checks the operation parameters and enqueues 3992108Sphk// the operation to the queue serviced by the attach listener. The thread created by 40105540Sphk// the client is a native thread and is restricted to a single page of stack. To keep 4192108Sphk// it simple operations are pre-allocated at initialization time. An enqueue thus 4292108Sphk// takes a preallocated operation, populates the operation parameters, adds it to 4392108Sphk// queue and wakes up the attach listener. 4492108Sphk// 4592108Sphk// When an operation has completed the attach listener is required to send the 4696952Sphk// operation result and any result data to the client. In this implementation the 4792108Sphk// client is a pipe server. In the enqueue operation it provides the name of pipe 4892108Sphk// to this process. When the operation is completed this process opens the pipe and 4992108Sphk// sends the result and output back to the client. Note that writing to the pipe 5092108Sphk// (and flushing the output) is a blocking operation. This means that a non-responsive 5192108Sphk// client could potentially hang the attach listener thread indefinitely. In that 5292108Sphk// case no new operations would be executed but the VM would continue as normal. 5392108Sphk// As only suitably privileged processes can open this process we concluded that 5492108Sphk// this wasn't worth worrying about. 5592108Sphk 5692108Sphk 5792108Sphk// forward reference 5892108Sphkclass Win32AttachOperation; 5992108Sphk 6092108Sphk 6192108Sphkclass Win32AttachListener: AllStatic { 6292108Sphk private: 6392108Sphk enum { 6492108Sphk preallocate_count = 4 // number of preallocated operations 6593776Sphk }; 6693776Sphk 6793776Sphk // protects the preallocated list and the operation list 6893776Sphk static HANDLE _mutex; 6995321Sphk 7092108Sphk // head of preallocated operations list 7192108Sphk static Win32AttachOperation* _avail; 7292108Sphk 7392108Sphk // head and tail of enqueue operations list 7492371Sphk static Win32AttachOperation* _head; 7592371Sphk static Win32AttachOperation* _tail; 76104057Sphk 77104057Sphk 7892108Sphk static Win32AttachOperation* head() { return _head; } 7992108Sphk static void set_head(Win32AttachOperation* head) { _head = head; } 8092108Sphk 8192108Sphk static Win32AttachOperation* tail() { return _tail; } 8293776Sphk static void set_tail(Win32AttachOperation* tail) { _tail = tail; } 8392108Sphk 8492108Sphk 8592108Sphk // used to wakeup the listener 8692108Sphk static HANDLE _wakeup; 8792108Sphk static HANDLE wakeup() { return _wakeup; } 8892108Sphk 8992108Sphk public: 9092108Sphk enum { 9192108Sphk ATTACH_ERROR_DISABLED = 100, // error codes 9292108Sphk ATTACH_ERROR_RESOURCE = 101, 9392108Sphk ATTACH_ERROR_ILLEGALARG = 102, 9492108Sphk ATTACH_ERROR_INTERNAL = 103 9592108Sphk }; 9692108Sphk 9792108Sphk static int init(); 9892108Sphk static HANDLE mutex() { return _mutex; } 9992108Sphk 10092108Sphk static Win32AttachOperation* available() { return _avail; } 10192108Sphk static void set_available(Win32AttachOperation* avail) { _avail = avail; } 10292108Sphk 10392108Sphk // enqueue an operation to the end of the list 10492108Sphk static int enqueue(char* cmd, char* arg1, char* arg2, char* arg3, char* pipename); 10592108Sphk 10692108Sphk // dequeue an operation from from head of the list 10792108Sphk static Win32AttachOperation* dequeue(); 10892108Sphk}; 10992108Sphk 11092108Sphk// statics 11192108SphkHANDLE Win32AttachListener::_mutex; 11292108SphkHANDLE Win32AttachListener::_wakeup; 11392108SphkWin32AttachOperation* Win32AttachListener::_avail; 11492108SphkWin32AttachOperation* Win32AttachListener::_head; 11592108SphkWin32AttachOperation* Win32AttachListener::_tail; 11692108Sphk 11792108Sphk 11892108Sphk// Win32AttachOperation is an AttachOperation that additionally encapsulates the name 11992108Sphk// of a pipe which is used to send the operation reply/output to the client. 12092108Sphk// Win32AttachOperation can also be linked in a list. 12192108Sphk 12292108Sphkclass Win32AttachOperation: public AttachOperation { 12392108Sphk private: 124107522Sphk friend class Win32AttachListener; 125107522Sphk 126107522Sphk enum { 127107522Sphk pipe_name_max = 256 // maximum pipe name 128107522Sphk }; 129107522Sphk 130107522Sphk char _pipe[pipe_name_max+1]; 131107522Sphk 132107522Sphk const char* pipe() const { return _pipe; } 133107522Sphk void set_pipe(const char* pipe) { 134107522Sphk assert(strlen(pipe) <= pipe_name_max, "execeds maximum length of pipe name"); 135107522Sphk strcpy(_pipe, pipe); 136107522Sphk } 137107522Sphk 138107522Sphk HANDLE open_pipe(); 139107522Sphk static BOOL write_pipe(HANDLE hPipe, char* buf, int len); 140107522Sphk 141107522Sphk Win32AttachOperation* _next; 142107522Sphk 143107522Sphk Win32AttachOperation* next() const { return _next; } 144107522Sphk void set_next(Win32AttachOperation* next) { _next = next; } 145107522Sphk 146107522Sphk // noarg constructor as operation is preallocated 147107522Sphk Win32AttachOperation() : AttachOperation("<noname>") { 148107522Sphk set_pipe("<nopipe>"); 149107522Sphk set_next(NULL); 150107522Sphk } 151107522Sphk 152107522Sphk public: 153107522Sphk void Win32AttachOperation::complete(jint result, bufferedStream* result_stream); 154107522Sphk}; 155107522Sphk 15693776Sphk 15792108Sphk// preallocate the required number of operations 15892108Sphkint Win32AttachListener::init() { 15992108Sphk _mutex = (void*)::CreateMutex(NULL, FALSE, NULL); 16092108Sphk guarantee(_mutex != (HANDLE)NULL, "mutex creation failed"); 16192108Sphk 16292108Sphk _wakeup = ::CreateSemaphore(NULL, 0, 1, NULL); 16392108Sphk guarantee(_wakeup != (HANDLE)NULL, "semaphore creation failed"); 164107522Sphk 165107522Sphk set_head(NULL); 166107522Sphk set_tail(NULL); 16794287Sphk 16892108Sphk // preallocate a few operations 16992108Sphk set_available(NULL); 17092108Sphk for (int i=0; i<preallocate_count; i++) { 17192108Sphk Win32AttachOperation* op = new Win32AttachOperation(); 17292108Sphk op->set_next(available()); 17392108Sphk set_available(op); 17494287Sphk } 17592108Sphk 17692108Sphk return 0; 17792108Sphk} 17892108Sphk 17992108Sphk// Enqueue an operation. This is called from a native thread that is not attached to VM. 180104195Sphk// Also we need to be careful not to execute anything that results in more than a 4k stack. 18192108Sphk// 18292108Sphkint Win32AttachListener::enqueue(char* cmd, char* arg0, char* arg1, char* arg2, char* pipename) { 183107522Sphk // listener not running 184107522Sphk if (!AttachListener::is_initialized()) { 185107522Sphk return ATTACH_ERROR_DISABLED; 186107522Sphk } 187107832Sphk 188107522Sphk // check that all paramteres to the operation 189107522Sphk if (strlen(cmd) > AttachOperation::name_length_max) return ATTACH_ERROR_ILLEGALARG; 190107832Sphk if (strlen(arg0) > AttachOperation::arg_length_max) return ATTACH_ERROR_ILLEGALARG; 191107522Sphk if (strlen(arg0) > AttachOperation::arg_length_max) return ATTACH_ERROR_ILLEGALARG; 192107832Sphk if (strlen(pipename) > Win32AttachOperation::pipe_name_max) return ATTACH_ERROR_ILLEGALARG; 193107522Sphk 194107522Sphk // check for a well-formed pipename 195107522Sphk if (strstr(pipename, "\\\\.\\pipe\\") != pipename) return ATTACH_ERROR_ILLEGALARG; 196107522Sphk 197107522Sphk // grab the lock for the list 198107522Sphk DWORD res = ::WaitForSingleObject(mutex(), INFINITE); 199107522Sphk if (res != WAIT_OBJECT_0) { 200107522Sphk return ATTACH_ERROR_INTERNAL; 201107522Sphk } 202107522Sphk 20392108Sphk // try to get an operation from the available list 204104057Sphk Win32AttachOperation* op = available(); 205104195Sphk if (op != NULL) { 206104057Sphk set_available(op->next()); 207104057Sphk 20892108Sphk // add to end (tail) of list 20992108Sphk op->set_next(NULL); 21092108Sphk if (tail() == NULL) { 21192108Sphk set_head(op); 21292108Sphk } else { 21392108Sphk tail()->set_next(op); 21492108Sphk } 21592108Sphk set_tail(op); 21694287Sphk 21794287Sphk op->set_name(cmd); 21894287Sphk op->set_arg(0, arg0); 21994287Sphk op->set_arg(1, arg1); 22094287Sphk op->set_arg(2, arg2); 22194287Sphk op->set_pipe(pipename); 22294287Sphk 22394287Sphk // wakeup the thread waiting for operations 22494287Sphk ::ReleaseSemaphore(wakeup(), 1, NULL); 22594287Sphk } 22694287Sphk ::ReleaseMutex(mutex()); 22794287Sphk 22898066Sphk return (op != NULL) ? 0 : ATTACH_ERROR_RESOURCE; 22992108Sphk} 23094287Sphk 23195310Sphk 23295038Sphk// dequeue the operation from the head of the operation list. If 23395038SphkWin32AttachOperation* Win32AttachListener::dequeue() { 23495038Sphk for (;;) { 23595038Sphk DWORD res = ::WaitForSingleObject(wakeup(), INFINITE); 23695038Sphk guarantee(res == WAIT_OBJECT_0, "wait failed"); 23795038Sphk 23895038Sphk res = ::WaitForSingleObject(mutex(), INFINITE); 23995038Sphk guarantee(res == WAIT_OBJECT_0, "wait failed"); 24095038Sphk 24195310Sphk Win32AttachOperation* op = head(); 24292108Sphk if (op != NULL) { 243104081Sphk set_head(op->next()); 244104195Sphk if (head() == NULL) { // list is empty 245104081Sphk set_tail(NULL); 246104081Sphk } 24792108Sphk } 24892108Sphk ::ReleaseMutex(mutex()); 24992108Sphk 25092108Sphk if (op != NULL) { 251104195Sphk return op; 25292108Sphk } 25392108Sphk } 25492108Sphk} 25592108Sphk 25692108Sphk 257104087Sphk// open the pipe to the client 25892108SphkHANDLE Win32AttachOperation::open_pipe() { 25992108Sphk HANDLE hPipe; 26092108Sphk 26192108Sphk hPipe = ::CreateFile( pipe(), // pipe name 262106101Sphk GENERIC_WRITE, // write only 263106101Sphk 0, // no sharing 264106101Sphk NULL, // default security attributes 265106101Sphk OPEN_EXISTING, // opens existing pipe 266106101Sphk 0, // default attributes 267106101Sphk NULL); // no template file 26895323Sphk 269105540Sphk if (hPipe != INVALID_HANDLE_VALUE) { 270105540Sphk // shouldn't happen as there is a pipe created per operation 27194287Sphk if (::GetLastError() == ERROR_PIPE_BUSY) { 27292108Sphk return INVALID_HANDLE_VALUE; 27392108Sphk } 274105540Sphk } 275105540Sphk return hPipe; 276105540Sphk} 277105540Sphk 278105540Sphk// write to the pipe 279105540SphkBOOL Win32AttachOperation::write_pipe(HANDLE hPipe, char* buf, int len) { 280105540Sphk do { 281105540Sphk DWORD nwrote; 28292108Sphk 28392108Sphk BOOL fSuccess = WriteFile( hPipe, // pipe handle 28492108Sphk (LPCVOID)buf, // message 285104064Sphk (DWORD)len, // message length 286107522Sphk &nwrote, // bytes written 287104064Sphk NULL); // not overlapped 288104064Sphk if (!fSuccess) { 289104064Sphk return fSuccess; 290104064Sphk } 291104064Sphk buf += nwrote; 292104064Sphk len -= nwrote; 293104064Sphk } 294104064Sphk while (len > 0); 295104195Sphk return TRUE; 296104195Sphk} 297104064Sphk 298104064Sphk// Complete the operation: 299104064Sphk// - open the pipe to the client 300104064Sphk// - write the operation result (a jint) 301104064Sphk// - write the operation output (the result stream) 302104064Sphk// 303104064Sphkvoid Win32AttachOperation::complete(jint result, bufferedStream* result_stream) { 304104064Sphk JavaThread* thread = JavaThread::current(); 305104064Sphk ThreadBlockInVM tbivm(thread); 306104064Sphk 307104064Sphk thread->set_suspend_equivalent(); 308104064Sphk // cleared by handle_special_suspend_equivalent_condition() or 309104064Sphk // java_suspend_self() via check_and_wait_while_suspended() 310104064Sphk 311104064Sphk HANDLE hPipe = open_pipe(); 312104064Sphk if (hPipe != INVALID_HANDLE_VALUE) { 313104064Sphk BOOL fSuccess; 314104064Sphk 315104064Sphk char msg[32]; 316104064Sphk sprintf(msg, "%d\n", result); 317104064Sphk 318104064Sphk fSuccess = write_pipe(hPipe, msg, (int)strlen(msg)); 319105542Sphk if (fSuccess) { 320105957Sphk write_pipe(hPipe, (char*) result_stream->base(), (int)(result_stream->size())); 321105957Sphk } 322105957Sphk 323105957Sphk // Need to flush buffers 324105957Sphk FlushFileBuffers(hPipe); 325104064Sphk CloseHandle(hPipe); 326104064Sphk } 327104064Sphk 328104064Sphk DWORD res = ::WaitForSingleObject(Win32AttachListener::mutex(), INFINITE); 329104064Sphk if (res == WAIT_OBJECT_0) { 330105957Sphk 331105957Sphk // put the operation back on the available list 332105957Sphk set_next(Win32AttachListener::available()); 333105957Sphk Win32AttachListener::set_available(this); 334105957Sphk 335107116Sphk ::ReleaseMutex(Win32AttachListener::mutex()); 336105957Sphk } 337105957Sphk 338104064Sphk // were we externally suspended while we were waiting? 339104064Sphk thread->check_and_wait_while_suspended(); 340104064Sphk} 341104064Sphk 342104064Sphk 343105957Sphk// AttachOperation functions 344105957Sphk 345105957SphkAttachOperation* AttachListener::dequeue() { 346105957Sphk JavaThread* thread = JavaThread::current(); 347104064Sphk ThreadBlockInVM tbivm(thread); 348105542Sphk 349105542Sphk thread->set_suspend_equivalent(); 350104064Sphk // cleared by handle_special_suspend_equivalent_condition() or 351104064Sphk // java_suspend_self() via check_and_wait_while_suspended() 352104064Sphk 353104064Sphk AttachOperation* op = Win32AttachListener::dequeue(); 354104064Sphk 355104064Sphk // were we externally suspended while we were waiting? 356104064Sphk thread->check_and_wait_while_suspended(); 357107522Sphk 358107522Sphk return op; 359107522Sphk} 360107522Sphk 361107522Sphkint AttachListener::pd_init() { 362107522Sphk return Win32AttachListener::init(); 363107522Sphk} 364107522Sphk 365107522Sphk// always startup on Windows NT/2000/XP 366107522Sphkbool AttachListener::init_at_startup() { 367107522Sphk return os::win32::is_nt(); 368107522Sphk} 369107522Sphk 370107522Sphk// no trigger mechanism on Windows to start Attach Listener lazily 371107522Sphkbool AttachListener::is_init_trigger() { 372107522Sphk return false; 373107522Sphk} 374107522Sphk 375107522Sphkvoid AttachListener::abort() { 376107522Sphk // nothing to do 377107522Sphk} 378107522Sphk 379107522Sphkvoid AttachListener::pd_data_dump() { 380107522Sphk os::signal_notify(SIGBREAK); 381107522Sphk} 382107522Sphk 383107522SphkAttachOperationFunctionInfo* AttachListener::pd_find_operation(const char* n) { 384107522Sphk return NULL; 385107522Sphk} 38692108Sphk 387105542Sphkjint AttachListener::pd_set_flag(AttachOperation* op, outputStream* out) { 38892108Sphk out->print_cr("flag '%s' cannot be changed", op->arg(0)); 38992108Sphk return JNI_ERR; 39092108Sphk} 39192108Sphk 39292108Sphkvoid AttachListener::pd_detachall() { 39392108Sphk // do nothing for now 39492108Sphk} 395104064Sphk 39692108Sphk// Native thread started by remote client executes this. 39792108Sphkextern "C" { 39892108Sphk JNIEXPORT jint JNICALL 39992108Sphk JVM_EnqueueOperation(char* cmd, char* arg0, char* arg1, char* arg2, char* pipename) { 40092108Sphk return (jint)Win32AttachListener::enqueue(cmd, arg0, arg1, arg2, pipename); 40192108Sphk } 40292108Sphk 40392108Sphk} // extern 40492108Sphk