Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: jruby/jruby
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 81cc0f1673d0
Choose a base ref
...
head repository: jruby/jruby
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 75712be489d9
Choose a head ref
  • 7 commits
  • 10 files changed
  • 1 contributor

Commits on Mar 2, 2016

  1. 3
    Copy the full SHA
    518703d View commit details
  2. Copy the full SHA
    4c0bd0e View commit details
  3. Copy the full SHA
    20587e9 View commit details
  4. Copy the full SHA
    fda62ae View commit details
  5. Copy the full SHA
    1475f6f View commit details
  6. Copy the full SHA
    5d5764c View commit details
  7. Copy the full SHA
    75712be View commit details
52 changes: 52 additions & 0 deletions test/truffle/integration/instrumentation-server.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
#!/usr/bin/env bash

set -e

ruby -X+T -Xtruffle.instrumentation_server_port=8080 test/truffle/integration/instrumentation-server/subject.rb &
pid=$!

while ! (curl -s http://localhost:8080/stacks > /dev/null);
do
echo -n .
sleep 1
done

if [[ $(curl -s http://localhost:8080/stacks) != *"test/truffle/integration/instrumentation-server/subject.rb:1"* ]]
then
echo Expected line not found in stacks
exit 1
fi

kill -9 $pid || true
wait $pid || true

( echo backtrace ; echo 20000+1400 ; echo continue ) > in.txt
ruby -X+T -Xtruffle.instrumentation_server_port=8080 test/truffle/integration/instrumentation-server/subject.rb < in.txt > out.txt &
pid=$!

while ! (curl -s http://localhost:8080/stacks > /dev/null);
do
echo -n .
sleep 1
done

curl -s http://localhost:8080/break

sleep 1
kill -9 $pid || true
wait $pid || true

session=$(cat out.txt)
rm -f in.txt out.txt

if [[ $session != *"test/truffle/integration/instrumentation-server/subject.rb:1"* ]]
then
echo Expected line not found in backtrace
exit 1
fi

if [[ $session != *21400* ]]
then
echo Expected value not found after eval
exit 1
fi
2 changes: 2 additions & 0 deletions test/truffle/integration/instrumentation-server/subject.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
loop do
end
2 changes: 1 addition & 1 deletion tool/jt.rb
Original file line number Diff line number Diff line change
@@ -181,7 +181,7 @@ def raw_sh(*args)
false
else
$stderr.puts "FAILED (#{$?}): #{printable_cmd(args)}"
if $?
if $? and $?.exitstatus
exit $?.exitstatus
else
exit 1
Original file line number Diff line number Diff line change
@@ -58,7 +58,7 @@
import org.jruby.truffle.language.methods.InternalMethod;
import org.jruby.truffle.language.parser.ParserContext;
import org.jruby.truffle.platform.Graal;
import org.jruby.truffle.tools.SimpleShell;
import org.jruby.truffle.tools.simpleshell.SimpleShell;
import org.jruby.util.ByteList;
import org.jruby.util.Memo;
import org.jruby.util.unsafe.UnsafeHolder;
Original file line number Diff line number Diff line change
@@ -21,36 +21,32 @@
import org.jruby.truffle.language.SafepointAction;
import org.jruby.truffle.language.backtrace.Backtrace;
import org.jruby.truffle.language.backtrace.BacktraceFormatter;
import org.jruby.truffle.tools.simpleshell.SimpleShell;

import java.io.IOException;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.util.List;

@SuppressWarnings("restriction")
public class InstrumentationServerManager {

private final RubyContext context;
private final int port;
private final HttpServer server; // not final as we want a gentler failure
private final HttpServer server;

private volatile boolean shuttingDown = false;

public InstrumentationServerManager(RubyContext context, int port) {
this.context = context;
this.port = port;

HttpServer server = null;

try {
server = HttpServer.create(new InetSocketAddress(port), 0);
} catch (IOException e) {
e.printStackTrace();
}
this.server = server;
}

public int getPort() {
return port;
this.server = server;
}

public void start() {
@@ -61,26 +57,37 @@ public void handle(HttpExchange httpExchange) {
try {
final StringBuilder builder = new StringBuilder();

final Thread serverThread = Thread.currentThread();

context.getSafepointManager().pauseAllThreadsAndExecuteFromNonRubyThread(false, new SafepointAction() {
@Override
public void run(DynamicObject thread, Node currentNode) {
try {
Backtrace backtrace = context.getCallStack().getBacktrace(null);
synchronized (this) {
if (Thread.currentThread() == serverThread) {
return;
}

try {
final Backtrace backtrace = context.getCallStack().getBacktrace(null);

final List<String> lines = BacktraceFormatter.createDefaultFormatter(context)
.formatBacktrace(context, null, backtrace);

synchronized (this) {
// Not thread-safe so keep the formatting synchronized for now.
final List<String> lines = BacktraceFormatter.createDefaultFormatter(context).formatBacktrace(context, null, backtrace);
builder.append(String.format("#%d %s",
Thread.currentThread().getId(),
Thread.currentThread().getName()));

builder.append(String.format("#%d %s", Thread.currentThread().getId(), Thread.currentThread().getName()));
builder.append("\n");

for (String line : lines) {
builder.append(line);
builder.append("\n");
}

builder.append("\n");
} catch (Throwable e) {
e.printStackTrace();
}
} catch (Throwable e) {
e.printStackTrace();
}
}
});
@@ -97,6 +104,7 @@ public void run(DynamicObject thread, Node currentNode) {
if (shuttingDown) {
return;
}

e.printStackTrace();
}
}
@@ -108,13 +116,18 @@ public void run(DynamicObject thread, Node currentNode) {
@Override
public void handle(HttpExchange httpExchange) {
try {
Thread mainThread = Layouts.FIBER.getThread((Layouts.THREAD.getFiberManager(context.getThreadManager().getRootThread()).getCurrentFiber()));
final Thread mainThread = Layouts.FIBER.getThread(
Layouts.THREAD.getFiberManager(context.getThreadManager().getRootThread())
.getCurrentFiber());

context.getSafepointManager().pauseThreadAndExecuteLaterFromNonRubyThread(mainThread, new SafepointAction() {

@Override
public void run(DynamicObject thread, final Node currentNode) {
new SimpleShell(context).run(Truffle.getRuntime().getCurrentFrame()
.getFrame(FrameInstance.FrameAccess.MATERIALIZE, true).materialize(), currentNode);
}

});

httpExchange.getResponseHeaders().set("Content-Type", "text/plain");
@@ -124,6 +137,7 @@ public void run(DynamicObject thread, final Node currentNode) {
if (shuttingDown) {
return;
}

e.printStackTrace();
}
}
108 changes: 0 additions & 108 deletions truffle/src/main/java/org/jruby/truffle/tools/SimpleShell.java

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/*
* Copyright (c) 2016 Oracle and/or its affiliates. All rights reserved. This
* code is released under a tri EPL/GPL/LGPL license. You can use it,
* redistribute it and/or modify it under the terms of the:
*
* Eclipse Public License version 1.0
* GNU General Public License version 2
* GNU Lesser General Public License version 2.1
*/
package org.jruby.truffle.tools.simpleshell;

import java.io.PrintWriter;

public class ConsoleShellInterface implements ShellInterface {

@Override
public String readLine(String prompt) {
return System.console().readLine(prompt);
}

@Override
public PrintWriter getWriter() {
return System.console().writer();
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/*
* Copyright (c) 2016 Oracle and/or its affiliates. All rights reserved. This
* code is released under a tri EPL/GPL/LGPL license. You can use it,
* redistribute it and/or modify it under the terms of the:
*
* Eclipse Public License version 1.0
* GNU General Public License version 2
* GNU Lesser General Public License version 2.1
*/
package org.jruby.truffle.tools.simpleshell;

import java.io.IOException;
import java.io.PrintWriter;

public interface ShellInterface {

String readLine(String prompt) throws IOException;

PrintWriter getWriter();

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
/*
* Copyright (c) 2013, 2016 Oracle and/or its affiliates. All rights reserved. This
* code is released under a tri EPL/GPL/LGPL license. You can use it,
* redistribute it and/or modify it under the terms of the:
*
* Eclipse Public License version 1.0
* GNU General Public License version 2
* GNU Lesser General Public License version 2.1
*/
package org.jruby.truffle.tools.simpleshell;

import com.oracle.truffle.api.frame.MaterializedFrame;
import com.oracle.truffle.api.nodes.Node;
import com.oracle.truffle.api.object.DynamicObject;
import com.oracle.truffle.api.source.Source;
import org.jcodings.specific.UTF8Encoding;
import org.jruby.truffle.RubyContext;
import org.jruby.truffle.core.Layouts;
import org.jruby.truffle.language.RubyRootNode;
import org.jruby.truffle.language.arguments.RubyArguments;
import org.jruby.truffle.language.backtrace.Activation;
import org.jruby.truffle.language.backtrace.BacktraceFormatter;
import org.jruby.truffle.language.control.RaiseException;
import org.jruby.truffle.language.parser.ParserContext;

import java.io.IOException;
import java.util.Collections;
import java.util.StringTokenizer;

public class SimpleShell {

private final RubyContext context;

private final ShellInterface shellInterface;

private int currentFrameIndex;
private MaterializedFrame currentFrame;

public SimpleShell(RubyContext context) {
this.context = context;

if (System.console() == null) {
shellInterface = new StandardShellInterface();
} else {
shellInterface = new ConsoleShellInterface();
}
}

public void run(MaterializedFrame frame, Node currentNode) {
currentFrameIndex = 0;
currentFrame = frame;

while (true) {
final String shellLine;

try {
shellLine = shellInterface.readLine("> ");
} catch (IOException e) {
e.printStackTrace();
return;
}

final StringTokenizer tokenizer = new StringTokenizer(shellLine);

if (!tokenizer.hasMoreElements()) {
continue;
}

switch (tokenizer.nextToken()) {
case "backtrace": {
final BacktraceFormatter formatter = BacktraceFormatter.createDefaultFormatter(context);

int n = 0;

for (Activation activation : context.getCallStack().getBacktrace(currentNode).getActivations()) {
if (n == currentFrameIndex) {
shellInterface.getWriter().print(" ▶ ");
} else {
shellInterface.getWriter().printf("%3d ", n);
}

shellInterface.getWriter().println(
formatter.formatLine(Collections.singletonList(activation), 0));

n++;
}
} break;

case "continue":
return;

case "exit": {
// We're in the debugger, not normal Ruby, so just hard exit here
System.exit(0);
} break;

case "frame": {
currentFrameIndex = Integer.parseInt(tokenizer.nextToken());

currentFrame = context.getCallStack()
.getBacktrace(currentNode)
.getActivations()
.get(currentFrameIndex).getMaterializedFrame();
} break;

default: {
try {
final RubyRootNode rootNode = context.getCodeLoader().parse(
Source.fromText(shellLine, "shell"),
UTF8Encoding.INSTANCE,
ParserContext.EVAL,
currentFrame,
false,
currentNode);

final Object result = context.getCodeLoader().execute(
ParserContext.EVAL,
RubyArguments.getDeclarationContext(currentFrame.getArguments()),
rootNode, currentFrame,
RubyArguments.getSelf(currentFrame.getArguments()));

String inspected;

try {
inspected = context.send(result, "inspect", null).toString();
} catch (Exception e) {
inspected = String.format("(error inspecting %s@%x %s)",
result.getClass().getSimpleName(),
result.hashCode(),
e.toString());
}

shellInterface.getWriter().println(inspected);
} catch (RaiseException e) {
final DynamicObject rubyException = e.getException();

final BacktraceFormatter formatter = BacktraceFormatter.createDefaultFormatter(context);
formatter.printBacktrace(context, rubyException, Layouts.EXCEPTION.getBacktrace(rubyException), shellInterface.getWriter());
}
} break;
}

shellInterface.getWriter().flush();
}
}


}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/*
* Copyright (c) 2016 Oracle and/or its affiliates. All rights reserved. This
* code is released under a tri EPL/GPL/LGPL license. You can use it,
* redistribute it and/or modify it under the terms of the:
*
* Eclipse Public License version 1.0
* GNU General Public License version 2
* GNU Lesser General Public License version 2.1
*/
package org.jruby.truffle.tools.simpleshell;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;

public class StandardShellInterface implements ShellInterface {

private final BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
private final PrintWriter writer = new PrintWriter(System.out);

@Override
public String readLine(String prompt) throws IOException {
System.out.print(prompt);
System.out.flush();
return reader.readLine();
}

@Override
public PrintWriter getWriter() {
return writer;
}

}