Skip to content

Commit

Permalink
Merge PR #144: Make Kompos tests more robust, include more info in fa…
Browse files Browse the repository at this point in the history
…ilures, and use ephemeral ports if necessary
  • Loading branch information
smarr committed May 6, 2017
2 parents 3ed3c17 + cecb092 commit 9ef1f72
Show file tree
Hide file tree
Showing 13 changed files with 240 additions and 138 deletions.
4 changes: 2 additions & 2 deletions .classpath
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
<classpathentry combineaccessrules="false" kind="src" path="/com.oracle.truffle.api.profiles"/>
<classpathentry kind="src" path="/com.oracle.truffle.tools"/>
<classpathentry kind="src" path="/com.oracle.truffle.tools.debug.shell"/>
<classpathentry kind="lib" path="libs/somns-deps-dev.jar"/>
<classpathentry kind="lib" path="libs/somns-deps.jar"/>
<classpathentry kind="lib" path="libs/somns-deps-dev.jar" sourcepath="libs/somns-deps-source.jar"/>
<classpathentry kind="lib" path="libs/somns-deps.jar" sourcepath="libs/somns-deps-source.jar"/>
<classpathentry kind="output" path="build/classes"/>
</classpath>
10 changes: 8 additions & 2 deletions build.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<property name="kompos.dir" value="tools/kompos" />
<property name="truffle.dir" value="${lib.dir}/truffle" />
<property name="truffle.build" value="${truffle.dir}/mxbuild/dists" />
<property name="somns-deps.version" value="0.3.2" />
<property name="somns-deps.version" value="0.3.3" />
<property name="checkstyle.version" value="7.6.1" />

<property name="build.dir" value="build"/>
Expand Down Expand Up @@ -57,7 +57,7 @@
</exec>
</target>

<target name="ideinit">
<target name="ideinit" depends="source">
<exec executable="../mx/mx" dir="${truffle.dir}" failonerror="true">
<arg value="eclipseinit"/>
</exec>
Expand All @@ -72,6 +72,12 @@
dest="${lib.dir}/somns-deps-dev.jar" />
</target>

<target name="source" description="Download Source Jars for development">
<get src="https://dl.bintray.com/smarr/SOM/somns-deps-source-${somns-deps.version}.jar"
usetimestamp="true"
dest="${lib.dir}/somns-deps-source.jar" />
</target>

<target name="checkstyle-jar">
<get src="http://tenet.dl.sourceforge.net/project/checkstyle/checkstyle/${checkstyle.version}/checkstyle-${checkstyle.version}-all.jar"
usetimestamp="true"
Expand Down
43 changes: 0 additions & 43 deletions src/tools/debugger/BinaryWebSocketHandler.java

This file was deleted.

127 changes: 79 additions & 48 deletions src/tools/debugger/FrontendConnector.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package tools.debugger;

import java.io.IOException;
import java.net.BindException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.util.ArrayList;
Expand All @@ -9,7 +10,7 @@
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.function.Function;

import org.java_websocket.WebSocket;

Expand All @@ -27,6 +28,8 @@
import tools.Tagging;
import tools.TraceData;
import tools.concurrency.ActorExecutionTrace;
import tools.debugger.WebSocketHandler.MessageHandler;
import tools.debugger.WebSocketHandler.TraceHandler;
import tools.debugger.entities.ActivityType;
import tools.debugger.entities.BreakpointType;
import tools.debugger.entities.EntityType;
Expand Down Expand Up @@ -64,15 +67,15 @@ public class FrontendConnector {
/**
* Receives requests from the client.
*/
private final WebSocketHandler receiver;
private final BinaryWebSocketHandler binaryHandler;
private final MessageHandler messageHandler;
private final TraceHandler traceHandler;

/**
* Sends requests to the client.
*/
private WebSocket sender;
private WebSocket messageSocket;

private WebSocket binarySender;
private WebSocket traceSocket;

/**
* Future to await the client's connection.
Expand All @@ -81,10 +84,11 @@ public class FrontendConnector {

private final Gson gson;
private static final int MESSAGE_PORT = 7977;
private static final int BINARY_PORT = 7978;
private static final int DEBUGGER_PORT = 8888;
private static final int TRACE_PORT = 7978;
private static final int HTTP_PORT = 8888;
private static final int EPHEMERAL_PORT = 0;

private final ArrayList<Source> notReady = new ArrayList<>(); // TODO rename: toBeSend
private final ArrayList<Source> sourceToBeSent = new ArrayList<>();

public FrontendConnector(final Breakpoints breakpoints,
final Instrumenter instrumenter, final WebDebugger webDebugger,
Expand All @@ -98,15 +102,16 @@ public FrontendConnector(final Breakpoints breakpoints,

try {
log("[DEBUGGER] Initialize HTTP and WebSocket Server for Debugger");
receiver = initializeWebSocket(MESSAGE_PORT, clientConnected);
log("[DEBUGGER] Started WebSocket Server");

binaryHandler = new BinaryWebSocketHandler(new InetSocketAddress(BINARY_PORT));
binaryHandler.start();

contentServer = initializeHttpServer(DEBUGGER_PORT);
messageHandler = initializeWebSocket(MESSAGE_PORT, port -> new MessageHandler(port, this, gson));
traceHandler = initializeWebSocket(TRACE_PORT, port -> new TraceHandler(port));
log("[DEBUGGER] Started WebSocket Servers");
log("[DEBUGGER] Message Handler: " + messageHandler.getPort());
log("[DEBUGGER] Trace Handler: " + traceHandler.getPort());

contentServer = initializeHttpServer(HTTP_PORT,
messageHandler.getPort(), traceHandler.getPort());
log("[DEBUGGER] Started HTTP Server");
log("[DEBUGGER] URL: http://localhost:" + DEBUGGER_PORT + "/index.html");
log("[DEBUGGER] URL: http://localhost:" + contentServer.getAddress().getPort() + "/index.html");
} catch (IOException e) {
log("Failed starting WebSocket and/or HTTP Server");
throw new RuntimeException(e);
Expand All @@ -119,27 +124,53 @@ public Breakpoints getBreakpoints() {
return breakpoints;
}

private WebSocketHandler initializeWebSocket(final int port,
final Future<WebSocket> clientConnected) {
InetSocketAddress address = new InetSocketAddress(port);
WebSocketHandler server = new WebSocketHandler(address, this, gson);
private <T extends WebSocketHandler> T tryInitializingWebSocket(final T server) throws Throwable {
server.start();
try {
server.awaitStartup();
} catch (ExecutionException e) {
throw e.getCause();
}
return server;
}

private HttpServer initializeHttpServer(final int port) throws IOException {
private <T extends WebSocketHandler> T initializeWebSocket(final int port, final Function<Integer, T> ctor) {
try {
return tryInitializingWebSocket(ctor.apply(port));
} catch (BindException e) {
try {
return tryInitializingWebSocket(ctor.apply(EPHEMERAL_PORT));
} catch (Throwable e1) {
throw new RuntimeException(e);
}
} catch (Throwable e) {
throw new RuntimeException(e);
}
}

private HttpServer tryInitializingHttpServer(final int port,
final int debuggerPort, final int tracePort) throws IOException {
InetSocketAddress address = new InetSocketAddress(port);
HttpServer httpServer = HttpServer.create(address, 0);
httpServer.createContext("/", new WebResourceHandler());
httpServer.createContext("/", new WebResourceHandler(debuggerPort, tracePort));
httpServer.setExecutor(null);
httpServer.start();
return httpServer;
}

private HttpServer initializeHttpServer(final int port,
final int debuggerPort, final int tracePort) throws IOException {
try {
return tryInitializingHttpServer(port, debuggerPort, tracePort);
} catch (BindException e) {
return tryInitializingHttpServer(EPHEMERAL_PORT, debuggerPort, tracePort);
}
}

private void ensureConnectionIsAvailable() {
assert receiver != null;
assert sender != null;
assert sender.isOpen();
assert messageHandler != null;
assert messageSocket != null;
assert messageSocket.isOpen();
}

// TODO: simplify, way to convoluted
Expand Down Expand Up @@ -180,25 +211,25 @@ private void sendSource(final Source source,

private void send(final Message msg) {
ensureConnectionIsAvailable();
sender.send(gson.toJson(msg, OutgoingMessage.class));
messageSocket.send(gson.toJson(msg, OutgoingMessage.class));
}

private void sendBufferedSources(
final Map<Source, Map<SourceSection, Set<Class<? extends Tags>>>> loadedSourcesTags,
final Map<Source, Set<RootNode>> rootNodes) {
if (!notReady.isEmpty()) {
for (Source s : notReady) {
if (!sourceToBeSent.isEmpty()) {
for (Source s : sourceToBeSent) {
sendSource(s, loadedSourcesTags, rootNodes.get(s));
}
notReady.clear();
sourceToBeSent.clear();
}
}

public void sendLoadedSource(final Source source,
final Map<Source, Map<SourceSection, Set<Class<? extends Tags>>>> loadedSourcesTags,
final Map<Source, Set<RootNode>> rootNodes) {
if (receiver == null || sender == null) {
notReady.add(source);
if (messageHandler == null || messageSocket == null) {
sourceToBeSent.add(source);
return;
}

Expand All @@ -212,18 +243,19 @@ public void sendSymbols(final ArrayList<SSymbol> symbolsToWrite) {
}

public void sendTracingData(final ByteBuffer b) {
binarySender.send(b);
traceSocket.send(b);
}

public void awaitClient() {
assert VmSettings.ACTOR_TRACING && VmSettings.TRUFFLE_DEBUGGER_ENABLED;
assert clientConnected != null;
assert binaryHandler.getConnection() != null;
assert messageSocket == null && traceSocket == null;
assert traceHandler.getConnection() != null;

log("[DEBUGGER] Waiting for debugger to connect.");
try {
sender = clientConnected.get();
if (VmSettings.ACTOR_TRACING) {
binarySender = binaryHandler.getConnection().get();
}
messageSocket = clientConnected.get();
traceSocket = traceHandler.getConnection().get();
} catch (InterruptedException | ExecutionException ex) {
throw new RuntimeException(ex);
}
Expand Down Expand Up @@ -278,25 +310,24 @@ static void log(final String str) {
}

public void completeConnection(final WebSocket conn) {
Runtime.getRuntime().addShutdownHook(new Thread(() -> closeAllSockets()));

clientConnected.complete(conn);
send(InitializationResponse.create(EntityType.values(),
ActivityType.values(), BreakpointType.values(), SteppingType.values()));
}

public void shutdown() {
int delaySec = 5;
contentServer.stop(delaySec);
private void closeAllSockets() {
final int delay = 0;
contentServer.stop(delay);

sender.close();
if (binarySender != null) {
binarySender.close();
messageSocket.close();
if (traceSocket != null) {
traceSocket.close();
}
try {
int delayMsec = 1000;
receiver.stop(delayMsec);
if (binarySender != null) {
binaryHandler.stop(delayMsec);
}
messageHandler.stop(delay);
traceHandler.stop(delay);
} catch (InterruptedException e) { }
}
}
2 changes: 1 addition & 1 deletion src/tools/debugger/WebDebugger.java
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ public static void log(final String str) {

@Override
protected void onDispose(final Env env) {
connector.shutdown();
/* NOOP: we close sockets with a VM shutdown hook */
}

@Override
Expand Down
15 changes: 15 additions & 0 deletions src/tools/debugger/WebResourceHandler.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,21 @@
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.charset.Charset;

import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;

import som.vm.NotYetImplementedException;

class WebResourceHandler implements HttpHandler {
private final int debuggerPort;
private final int tracePort;

WebResourceHandler(final int debuggerPort, final int tracePort) {
this.debuggerPort = debuggerPort;
this.tracePort = tracePort;
}

@Override
public void handle(final HttpExchange exchange) throws IOException {
Expand All @@ -36,10 +44,17 @@ public void handle(final HttpExchange exchange) throws IOException {
}
exchange.sendResponseHeaders(200, f.length());
copy(f, exchange.getResponseBody());
exchange.close();
return;
}

switch (requestedFile) {
case "/ports.json":
String jsonPorts = "{\"dbgPort\":" + debuggerPort + ",\"tracePort\":" + tracePort + "\"}";
exchange.sendResponseHeaders(200, jsonPorts.length());
exchange.getResponseBody().write(jsonPorts.getBytes(Charset.forName("UTF-8")));
exchange.close();
return;
case "/favicon.ico":
exchange.sendResponseHeaders(404, 0);
exchange.close();
Expand Down
Loading

0 comments on commit 9ef1f72

Please sign in to comment.