/** Redirect a VMs output and error streams to System.out and System.err */ protected void redirectStreams(VirtualMachine vm) { MessageSiphon ms = new MessageSiphon(process.getErrorStream(), this); errThread = ms.getThread(); outThread = new StreamRedirectThread("VM output reader", process.getInputStream(), System.out); errThread.start(); outThread.start(); }
/** * Generate the trace. Enable events, start thread to display events, start threads to forward * remote error and output streams, resume the remote VM, wait for the final event, and shutdown. */ protected void generateTrace() { // vm.setDebugTraceMode(debugTraceMode); // vm.setDebugTraceMode(VirtualMachine.TRACE_ALL); // vm.setDebugTraceMode(VirtualMachine.TRACE_NONE); // formerly, seems to have no effect // For internal debugging PrintWriter writer = null; // Calling this seems to set something internally to make the // Eclipse JDI wake up. Without it, an ObjectCollectedException // is thrown on excReq.enable(). No idea why this works, // but at least exception handling has returned. (Suspect that it may // block until all or at least some threads are available, meaning // that the app has launched and we have legit objects to talk to). vm.allThreads(); // The bug may not have been noticed because the test suite waits for // a thread to be available, and queries it by calling allThreads(). // See org.eclipse.debug.jdi.tests.AbstractJDITest for the example. EventRequestManager mgr = vm.eventRequestManager(); // get only the uncaught exceptions ExceptionRequest excReq = mgr.createExceptionRequest(null, false, true); // System.out.println(excReq); // this version reports all exceptions, caught or uncaught // ExceptionRequest excReq = mgr.createExceptionRequest(null, true, true); // suspend so we can step excReq.setSuspendPolicy(EventRequest.SUSPEND_ALL); // excReq.setSuspendPolicy(EventRequest.SUSPEND_EVENT_THREAD); // excReq.setSuspendPolicy(EventRequest.SUSPEND_NONE); // another option? excReq.enable(); Thread eventThread = new Thread() { public void run() { try { boolean connected = true; while (connected) { EventQueue eventQueue = vm.eventQueue(); // remove() blocks until event(s) available EventSet eventSet = eventQueue.remove(); // listener.vmEvent(eventSet); for (Event event : eventSet) { // System.out.println("EventThread.handleEvent -> " + event); if (event instanceof VMStartEvent) { vm.resume(); } else if (event instanceof ExceptionEvent) { // for (ThreadReference thread : vm.allThreads()) { // System.out.println("thread : " + thread); //// thread.suspend(); // } exceptionEvent((ExceptionEvent) event); } else if (event instanceof VMDisconnectEvent) { connected = false; } } } // } catch (VMDisconnectedException e) { // Logger.getLogger(VMEventReader.class.getName()).log(Level.INFO, // "VMEventReader quit on VM disconnect"); } catch (Exception e) { System.err.println("crashed in event thread due to " + e.getMessage()); // Logger.getLogger(VMEventReader.class.getName()).log(Level.SEVERE, // "VMEventReader quit", e); e.printStackTrace(); } } }; eventThread.start(); errThread = new MessageSiphon(process.getErrorStream(), this).getThread(); outThread = new StreamRedirectThread("JVM stdout Reader", process.getInputStream(), System.out); errThread.start(); outThread.start(); // Shutdown begins when event thread terminates try { if (eventThread != null) eventThread.join(); // is this the problem? // System.out.println("in here"); // Bug #852 tracked to this next line in the code. // http://dev.processing.org/bugs/show_bug.cgi?id=852 errThread.join(); // Make sure output is forwarded // System.out.println("and then"); outThread.join(); // before we exit // System.out.println("finished join for errThread and outThread"); // At this point, disable the run button. // This happens when the sketch is exited by hitting ESC, // or the user manually closes the sketch window. // TODO this should be handled better, should it not? if (editor != null) { editor.deactivateRun(); } } catch (InterruptedException exc) { // we don't interrupt } // System.out.println("and leaving"); if (writer != null) writer.close(); }