Skip to content

Commit

Permalink
customRequest 'processId' to get the debugging Java process id (#399)
Browse files Browse the repository at this point in the history
* customRequest 'processId' to get Java process id
* send a custom notification when processId/shellProcessId is ready
  • Loading branch information
testforstephen authored Mar 28, 2022
1 parent f704199 commit 8a1c975
Show file tree
Hide file tree
Showing 10 changed files with 162 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
import com.microsoft.java.debug.core.adapter.handler.InitializeRequestHandler;
import com.microsoft.java.debug.core.adapter.handler.InlineValuesRequestHandler;
import com.microsoft.java.debug.core.adapter.handler.LaunchRequestHandler;
import com.microsoft.java.debug.core.adapter.handler.ProcessIdHandler;
import com.microsoft.java.debug.core.adapter.handler.RefreshVariablesHandler;
import com.microsoft.java.debug.core.adapter.handler.RestartFrameHandler;
import com.microsoft.java.debug.core.adapter.handler.ScopesRequestHandler;
Expand Down Expand Up @@ -125,10 +126,11 @@ private void initialize() {
registerHandlerForDebug(new SetDataBreakpointsRequestHandler());
registerHandlerForDebug(new InlineValuesRequestHandler());
registerHandlerForDebug(new RefreshVariablesHandler());
registerHandlerForDebug(new ProcessIdHandler());

// NO_DEBUG mode only
registerHandlerForNoDebug(new DisconnectRequestWithoutDebuggingHandler());

registerHandlerForNoDebug(new ProcessIdHandler());
}

private void registerHandlerForDebug(IDebugRequestHandler handler) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@ public class DebugAdapterContext implements IDebugAdapterContext {
private Path classpathJar = null;
private Path argsfile = null;

private long shellProcessId = -1;
private long processId = -1;

private IdCollection<String> sourceReferences = new IdCollection<>();
private RecyclableObjectPool<Long, Object> recyclableIdPool = new RecyclableObjectPool<>();
private IVariableFormatter variableFormatter = VariableFormatterFactory.createVariableFormatter();
Expand Down Expand Up @@ -326,4 +329,24 @@ public IBreakpointManager getBreakpointManager() {
public IStepResultManager getStepResultManager() {
return stepResultManager;
}

@Override
public long getProcessId() {
return this.processId;
}

@Override
public long getShellProcessId() {
return this.shellProcessId;
}

@Override
public void setProcessId(long processId) {
this.processId = processId;
}

@Override
public void setShellProcessId(long shellProcessId) {
this.shellProcessId = shellProcessId;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -128,4 +128,12 @@ public interface IDebugAdapterContext {
IBreakpointManager getBreakpointManager();

IStepResultManager getStepResultManager();

void setShellProcessId(long shellProcessId);

long getShellProcessId();

void setProcessId(long processId);

long getProcessId();
}
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,17 @@ protected CompletableFuture<Response> handleLaunchCommand(Arguments arguments, R
}

return launch(launchArguments, response, context).thenCompose(res -> {
long processId = context.getProcessId();
long shellProcessId = context.getShellProcessId();
if (context.getDebuggeeProcess() != null) {
processId = context.getDebuggeeProcess().pid();
}

// If processId or shellProcessId exist, send a notification to client.
if (processId > 0 || shellProcessId > 0) {
context.getProtocolServer().sendEvent(new Events.ProcessIdNotification(processId, shellProcessId));
}

LaunchUtils.releaseTempLaunchFile(context.getClasspathJar());
LaunchUtils.releaseTempLaunchFile(context.getArgsfile());
if (res.success) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import org.apache.commons.lang3.SystemUtils;

import com.google.gson.JsonObject;
import com.google.gson.JsonSyntaxException;
import com.microsoft.java.debug.core.Configuration;
import com.microsoft.java.debug.core.DebugException;
import com.microsoft.java.debug.core.DebugSession;
Expand All @@ -45,6 +46,7 @@
import com.microsoft.java.debug.core.protocol.Requests.Command;
import com.microsoft.java.debug.core.protocol.Requests.LaunchArguments;
import com.microsoft.java.debug.core.protocol.Requests.RunInTerminalRequestArguments;
import com.microsoft.java.debug.core.protocol.Responses.RunInTerminalResponseBody;
import com.sun.jdi.VirtualMachine;
import com.sun.jdi.connect.Connector;
import com.sun.jdi.connect.IllegalConnectorArgumentsException;
Expand Down Expand Up @@ -102,6 +104,14 @@ public CompletableFuture<Response> launchInTerminal(LaunchArguments launchArgume
if (runResponse != null) {
if (runResponse.success) {
try {
try {
RunInTerminalResponseBody terminalResponse = JsonUtils.fromJson(
JsonUtils.toJson(runResponse.body), RunInTerminalResponseBody.class);
context.setProcessId(terminalResponse.processId);
context.setShellProcessId(terminalResponse.shellProcessId);
} catch (JsonSyntaxException e) {
logger.severe("Failed to resolve runInTerminal response: " + e.toString());
}
VirtualMachine vm = listenConnector.accept(args);
vmHandler.connectVirtualMachine(vm);
context.setDebugSession(new DebugSession(vm));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import java.util.logging.Logger;

import com.google.gson.JsonObject;
import com.google.gson.JsonSyntaxException;
import com.microsoft.java.debug.core.Configuration;
import com.microsoft.java.debug.core.DebugException;
import com.microsoft.java.debug.core.adapter.ErrorCode;
Expand All @@ -33,6 +34,7 @@
import com.microsoft.java.debug.core.protocol.Requests.Command;
import com.microsoft.java.debug.core.protocol.Requests.LaunchArguments;
import com.microsoft.java.debug.core.protocol.Requests.RunInTerminalRequestArguments;
import com.microsoft.java.debug.core.protocol.Responses.RunInTerminalResponseBody;
import com.sun.jdi.connect.IllegalConnectorArgumentsException;
import com.sun.jdi.connect.VMStartException;

Expand Down Expand Up @@ -112,8 +114,19 @@ public CompletableFuture<Response> launchInTerminal(LaunchArguments launchArgume
context.getProtocolServer().sendRequest(request, RUNINTERMINAL_TIMEOUT).whenComplete((runResponse, ex) -> {
if (runResponse != null) {
if (runResponse.success) {
// Without knowing the pid, debugger has lost control of the process.
// So simply send `terminated` event to end the session.
try {
RunInTerminalResponseBody terminalResponse = JsonUtils.fromJson(
JsonUtils.toJson(runResponse.body), RunInTerminalResponseBody.class);
context.setProcessId(terminalResponse.processId);
context.setShellProcessId(terminalResponse.shellProcessId);
} catch (JsonSyntaxException e) {
logger.severe("Failed to resolve runInTerminal response: " + e.toString());
}

// TODO: Since the RunInTerminal request will return the pid or parent shell
// pid now, the debugger is able to use this pid to monitor the lifecycle
// of the running Java process. There is no need to terminate the debug
// session early here.
context.getProtocolServer().sendEvent(new Events.TerminatedEvent());
resultFuture.complete(response);
} else {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*******************************************************************************
* Copyright (c) 2022 Microsoft Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Microsoft Corporation - initial API and implementation
*******************************************************************************/

package com.microsoft.java.debug.core.adapter.handler;

import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CompletableFuture;

import com.microsoft.java.debug.core.adapter.IDebugAdapterContext;
import com.microsoft.java.debug.core.adapter.IDebugRequestHandler;
import com.microsoft.java.debug.core.protocol.Messages.Response;
import com.microsoft.java.debug.core.protocol.Requests.Arguments;
import com.microsoft.java.debug.core.protocol.Requests.Command;
import com.microsoft.java.debug.core.protocol.Responses.ProcessIdResponseBody;

public class ProcessIdHandler implements IDebugRequestHandler {
@Override
public List<Command> getTargetCommands() {
return Arrays.asList(Command.PROCESSID);
}

@Override
public CompletableFuture<Response> handle(Command command, Arguments arguments, Response response,
IDebugAdapterContext context) {
long processId = context.getProcessId();
long shellProcessId = context.getShellProcessId();
if (context.getDebuggeeProcess() != null) {
processId = context.getDebuggeeProcess().pid();
}

response.body = new ProcessIdResponseBody(processId, shellProcessId);
return CompletableFuture.completedFuture(response);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -283,4 +283,26 @@ public InvalidatedEvent(InvalidatedAreas area, int frameId) {
this.frameId = frameId;
}
}

public static class ProcessIdNotification extends DebugEvent {
/**
* The process ID.
*/
public long processId = -1;
/**
* The process ID of the terminal shell if the process is running in a terminal shell.
*/
public long shellProcessId = -1;

public ProcessIdNotification(long processId) {
super("processid");
this.processId = processId;
}

public ProcessIdNotification(long processId, long shellProcessId) {
super("processid");
this.processId = processId;
this.shellProcessId = shellProcessId;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -410,6 +410,7 @@ public static enum Command {
PAUSEOTHERS("pauseOthers", ThreadOperationArguments.class),
INLINEVALUES("inlineValues", InlineValuesArguments.class),
REFRESHVARIABLES("refreshVariables", RefreshVariablesArguments.class),
PROCESSID("processId", Arguments.class),
UNSUPPORTED("", Arguments.class);

private String command;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,34 @@ public InitializeResponseBody(Types.Capabilities capabilities) {
}
}

public static class RunInTerminalResponseBody extends ResponseBody {
public int processId;
public static class ProcessIdResponseBody extends ResponseBody {
/**
* The process ID.
*/
public long processId = -1;
/**
* The process ID of the terminal shell if the process is running in a terminal shell.
*/
public long shellProcessId = -1;

public ProcessIdResponseBody(long processId) {
this.processId = processId;
}

public RunInTerminalResponseBody(int processId) {
public ProcessIdResponseBody(long processId, long shellProcessId) {
this.processId = processId;
this.shellProcessId = shellProcessId;
}
}

public static class RunInTerminalResponseBody extends ProcessIdResponseBody {

public RunInTerminalResponseBody(long processId) {
super(processId);
}

public RunInTerminalResponseBody(long processId, long shellProcessId) {
super(processId, shellProcessId);
}
}

Expand Down

0 comments on commit 8a1c975

Please sign in to comment.