Source:
<code>private void displaySourceFiles(DsfSession session, IDMContext dmcontext) { if (session.getExecutor().isShutdown()) { return; } IContainerDMContext containerDMContext = DMContexts.getAncestorOfType(dmcontext, IContainerDMContext.class); if (containerDMContext == null || Objects.equals(containerDMContext, this.dmcontext)) { return; } this.dmcontext = containerDMContext; session.getExecutor().submit(new DsfRunnable() { @Override public void run() { DsfServicesTracker tracker = new DsfServicesTracker(GdbUIPlugin.getBundleContext(), session.getId()); IDebugSourceFiles srcService = tracker.getService(IDebugSourceFiles.class); tracker.dispose(); if (srcService == null) { return; } srcService.getSources(containerDMContext, new DataRequestMonitor<IDebugSourceFileInfo[]>(session.getExecutor(), null) { @Override protected void handleSuccess() { IDebugSourceFileInfo[] srcFileInfo = getData(); <START> populateTreeJob.setSrcFileInfo(srcFileInfo); <END> if (populateTreeJob.getState() == Job.RUNNING) populateTreeJob.cancel(); populateTreeJob.schedule(); } @Override protected void handleError() { } }); } }); }</code><technical_language>This sorts of bizarre errors. changing internal state of populateTreeJob while is running. I fields in populateTreeJob final create new jobs time, ensuring I cancelled running jobs losing handle them. Creating populateTreeJob instances is cheap</technical_language>

Target:
private void displaySourceFiles(DsfSession session, IDMContext dmcontext) { if (session.getExecutor().isShutdown()) { return; } IContainerDMContext containerDMContext = DMContexts.getAncestorOfType(dmcontext, IContainerDMContext.class); if (containerDMContext == null || Objects.equals(containerDMContext, this.dmcontext)) { return; } this.dmcontext = containerDMContext; session.getExecutor().submit(new DsfRunnable() { @Override public void run() { DsfServicesTracker tracker = new DsfServicesTracker(GdbUIPlugin.getBundleContext(), session.getId()); IDebugSourceFiles srcService = tracker.getService(IDebugSourceFiles.class); tracker.dispose(); if (srcService == null) { return; } srcService.getSources(containerDMContext, new DataRequestMonitor<IDebugSourceFileInfo[]>(session.getExecutor(), null) { @Override protected void handleSuccess() { IDebugSourceFileInfo[] srcFileInfo = getData(); PopulateTreeJob populateTreeJob = new PopulateTreeJob(srcFileInfo); CheckFileExistenceJob checkFileExistenceJob = new CheckFileExistenceJob(); populateTreeJob.addJobChangeListener(new JobChangeAdapter() { @Override public void done(IJobChangeEvent event) { debugTree = (DebugTree<String>) populateTreeJob.getTree(); Display.getDefault().asyncExec(new Runnable() { @Override public void run() { if (!viewer.getControl().isDisposed()) { debugTree.toString(); viewer.setInput(debugTree); } } }); if (checkFileExistenceJob.getState() == Job.RUNNING) checkFileExistenceJob.cancel(); checkFileExistenceJob.schedule(); } }); checkFileExistenceJob.addJobChangeListener(new JobChangeAdapter() { @Override public void done(IJobChangeEvent event) { Display.getDefault().asyncExec(new Runnable() { @Override public void run() { if (!viewer.getControl().isDisposed()) { viewer.refresh(); } } }); } }); if (populateTreeJob.getState() == Job.RUNNING) populateTreeJob.cancel(); if (checkFileExistenceJob.getState() == Job.RUNNING) checkFileExistenceJob.cancel(); populateTreeJob.schedule(); } @Override protected void handleError() { } }); } }); }