Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/back/debugLoop.c
38765 views
/*1* Copyright (c) 1998, 2017, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425#include "util.h"26#include "transport.h"27#include "debugLoop.h"28#include "debugDispatch.h"29#include "standardHandlers.h"30#include "inStream.h"31#include "outStream.h"32#include "threadControl.h"333435static void JNICALL reader(jvmtiEnv* jvmti_env, JNIEnv* jni_env, void* arg);36static void enqueue(jdwpPacket *p);37static jboolean dequeue(jdwpPacket *p);38static void notifyTransportError(void);3940struct PacketList {41jdwpPacket packet;42struct PacketList *next;43};4445static volatile struct PacketList *cmdQueue;46static jrawMonitorID cmdQueueLock;47static jrawMonitorID vmDeathLock;48static jboolean transportError;4950static jboolean51lastCommand(jdwpCmdPacket *cmd)52{53if ((cmd->cmdSet == JDWP_COMMAND_SET(VirtualMachine)) &&54((cmd->cmd == JDWP_COMMAND(VirtualMachine, Dispose)) ||55(cmd->cmd == JDWP_COMMAND(VirtualMachine, Exit)))) {56return JNI_TRUE;57} else {58return JNI_FALSE;59}60}6162void63debugLoop_initialize(void)64{65vmDeathLock = debugMonitorCreate("JDWP VM_DEATH Lock");66}6768void69debugLoop_sync(void)70{71debugMonitorEnter(vmDeathLock);72debugMonitorExit(vmDeathLock);73}7475/*76* This is where all the work gets done.77*/7879void80debugLoop_run(void)81{82jboolean shouldListen;83jdwpPacket p;84jvmtiStartFunction func;8586/* Initialize all statics */87/* We may be starting a new connection after an error */88cmdQueue = NULL;89cmdQueueLock = debugMonitorCreate("JDWP Command Queue Lock");90transportError = JNI_FALSE;9192shouldListen = JNI_TRUE;9394func = &reader;95(void)spawnNewThread(func, NULL, "JDWP Command Reader");9697standardHandlers_onConnect();98threadControl_onConnect();99100/* Okay, start reading cmds! */101while (shouldListen) {102if (!dequeue(&p)) {103break;104}105106if (p.type.cmd.flags & JDWPTRANSPORT_FLAGS_REPLY) {107/*108* Its a reply packet.109*/110continue;111} else {112/*113* Its a cmd packet.114*/115jdwpCmdPacket *cmd = &p.type.cmd;116PacketInputStream in;117PacketOutputStream out;118CommandHandler func;119120/* Should reply be sent to sender.121* For error handling, assume yes, since122* only VM/exit does not reply123*/124jboolean replyToSender = JNI_TRUE;125126/*127* For all commands we hold the vmDeathLock128* while executing and replying to the command. This ensures129* that a command after VM_DEATH will be allowed to complete130* before the thread posting the VM_DEATH continues VM131* termination.132*/133debugMonitorEnter(vmDeathLock);134135/* Initialize the input and output streams */136inStream_init(&in, p);137outStream_initReply(&out, inStream_id(&in));138139LOG_MISC(("Command set %d, command %d", cmd->cmdSet, cmd->cmd));140141func = debugDispatch_getHandler(cmd->cmdSet,cmd->cmd);142if (func == NULL) {143/* we've never heard of this, so I guess we144* haven't implemented it.145* Handle gracefully for future expansion146* and platform / vendor expansion.147*/148outStream_setError(&out, JDWP_ERROR(NOT_IMPLEMENTED));149} else if (gdata->vmDead &&150((cmd->cmdSet) != JDWP_COMMAND_SET(VirtualMachine))) {151/* Protect the VM from calls while dead.152* VirtualMachine cmdSet quietly ignores some cmds153* after VM death, so, it sends it's own errors.154*/155outStream_setError(&out, JDWP_ERROR(VM_DEAD));156} else {157/* Call the command handler */158replyToSender = func(&in, &out);159}160161/* Reply to the sender */162if (replyToSender) {163if (inStream_error(&in)) {164outStream_setError(&out, inStream_error(&in));165}166outStream_sendReply(&out);167}168169/*170* Release the vmDeathLock as the reply has been posted.171*/172debugMonitorExit(vmDeathLock);173174inStream_destroy(&in);175outStream_destroy(&out);176177shouldListen = !lastCommand(cmd);178}179}180threadControl_onDisconnect();181standardHandlers_onDisconnect();182183/*184* Cut off the transport immediately. This has the effect of185* cutting off any events that the eventHelper thread might186* be trying to send.187*/188transport_close();189debugMonitorDestroy(cmdQueueLock);190191/* Reset for a new connection to this VM if it's still alive */192if ( ! gdata->vmDead ) {193debugInit_reset(getEnv());194}195}196197/* Command reader */198static void JNICALL199reader(jvmtiEnv* jvmti_env, JNIEnv* jni_env, void* arg)200{201jdwpPacket packet;202jdwpCmdPacket *cmd;203jboolean shouldListen = JNI_TRUE;204205LOG_MISC(("Begin reader thread"));206207while (shouldListen) {208jint rc;209210rc = transport_receivePacket(&packet);211212/* I/O error or EOF */213if (rc != 0 || (rc == 0 && packet.type.cmd.len == 0)) {214shouldListen = JNI_FALSE;215notifyTransportError();216} else if (packet.type.cmd.flags != JDWPTRANSPORT_FLAGS_NONE) {217/*218* Close the connection when we get a jdwpCmdPacket with an219* invalid flags field value. This is a protocol violation220* so we drop the connection. Also this could be a web221* browser generating an HTTP request that passes the JDWP222* handshake. HTTP requests requires that everything be in223* the ASCII printable range so a flags value of224* JDWPTRANSPORT_FLAGS_NONE(0) cannot be generated via HTTP.225*/226ERROR_MESSAGE(("Received jdwpPacket with flags != 0x%d (actual=0x%x) when a jdwpCmdPacket was expected.",227JDWPTRANSPORT_FLAGS_NONE, packet.type.cmd.flags));228shouldListen = JNI_FALSE;229notifyTransportError();230} else {231cmd = &packet.type.cmd;232233LOG_MISC(("Command set %d, command %d", cmd->cmdSet, cmd->cmd));234235/*236* FIXME! We need to deal with high priority237* packets and queue flushes!238*/239enqueue(&packet);240241shouldListen = !lastCommand(cmd);242}243}244LOG_MISC(("End reader thread"));245}246247/*248* The current system for queueing packets is highly249* inefficient, and should be rewritten! It'd be nice250* to avoid any additional memory allocations.251*/252253static void254enqueue(jdwpPacket *packet)255{256struct PacketList *pL;257struct PacketList *walker;258259pL = jvmtiAllocate((jint)sizeof(struct PacketList));260if (pL == NULL) {261EXIT_ERROR(AGENT_ERROR_OUT_OF_MEMORY,"packet list");262}263264pL->packet = *packet;265pL->next = NULL;266267debugMonitorEnter(cmdQueueLock);268269if (cmdQueue == NULL) {270cmdQueue = pL;271debugMonitorNotify(cmdQueueLock);272} else {273walker = (struct PacketList *)cmdQueue;274while (walker->next != NULL)275walker = walker->next;276277walker->next = pL;278}279280debugMonitorExit(cmdQueueLock);281}282283static jboolean284dequeue(jdwpPacket *packet) {285struct PacketList *node = NULL;286287debugMonitorEnter(cmdQueueLock);288289while (!transportError && (cmdQueue == NULL)) {290debugMonitorWait(cmdQueueLock);291}292293if (cmdQueue != NULL) {294node = (struct PacketList *)cmdQueue;295cmdQueue = node->next;296}297debugMonitorExit(cmdQueueLock);298299if (node != NULL) {300*packet = node->packet;301jvmtiDeallocate(node);302}303return (node != NULL);304}305306static void307notifyTransportError(void) {308debugMonitorEnter(cmdQueueLock);309transportError = JNI_TRUE;310debugMonitorNotify(cmdQueueLock);311debugMonitorExit(cmdQueueLock);312}313314315