From f5c2d9b4ff09518cce11d55571fb8e4ee2467c9d Mon Sep 17 00:00:00 2001 From: dragonmacher <48328597+dragonmacher@users.noreply.github.com> Date: Thu, 30 Jun 2022 12:44:27 -0400 Subject: [PATCH] GP-2265 - Fixed printing of buffer exception when closing program; added code for exception being printed in rare timing condition in tables --- .../DecompilerDataTypeReferenceFinder.java | 4 +++- .../src/main/java/db/buffers/BufferMgr.java | 21 ++++++++++++------- .../table/threaded/IncrementalLoadJob.java | 19 ++++++++++++----- 3 files changed, 30 insertions(+), 14 deletions(-) diff --git a/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/extension/datatype/finder/DecompilerDataTypeReferenceFinder.java b/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/extension/datatype/finder/DecompilerDataTypeReferenceFinder.java index 96911b14fd..f5eb994309 100644 --- a/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/extension/datatype/finder/DecompilerDataTypeReferenceFinder.java +++ b/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/extension/datatype/finder/DecompilerDataTypeReferenceFinder.java @@ -90,7 +90,9 @@ public class DecompilerDataTypeReferenceFinder implements DataTypeReferenceFinde } catch (InterruptedException e) { Thread.currentThread().interrupt(); // reset the flag - Msg.debug(this, "Interrupted while decompiling functions"); + if (!monitor.isCancelled()) { + Msg.debug(this, "Interrupted while decompiling functions"); + } } catch (Exception e) { Msg.error(this, "Encountered an exception decompiling functions", e); diff --git a/Ghidra/Framework/DB/src/main/java/db/buffers/BufferMgr.java b/Ghidra/Framework/DB/src/main/java/db/buffers/BufferMgr.java index 44da54de54..f2035b84b1 100644 --- a/Ghidra/Framework/DB/src/main/java/db/buffers/BufferMgr.java +++ b/Ghidra/Framework/DB/src/main/java/db/buffers/BufferMgr.java @@ -136,7 +136,7 @@ public class BufferMgr { private static final int INITIAL_BUFFER_TABLE_SIZE = 1024; /** - * An optional pre-cache of all buffers can be performed within a separate + * An optional pre-cache of all buffers can be performed within a separate * thread if enabled. */ private enum PreCacheStatus { @@ -257,7 +257,7 @@ public class BufferMgr { /** * Enable and start source buffer file pre-cache if appropriate. - * This may be forced for all use cases by setting the System property + * This may be forced for all use cases by setting the System property * db.always.precache=true * WARNING! EXPERIMENTAL !!! */ @@ -384,13 +384,13 @@ public class BufferMgr { public void dispose() { dispose(false); } - + /** * Dispose of all buffer manager resources including any source * buffer file. * This method should be called when this buffer manager instance * is no longer needed. - * @param keepRecoveryData true if existing snapshot recovery files + * @param keepRecoveryData true if existing snapshot recovery files * should not be deleted. */ public void dispose(boolean keepRecoveryData) { @@ -689,7 +689,7 @@ public class BufferMgr { /** * Start pre-cache of source file if appropriate. - * This targets remote buffer file adapters only. + * This targets remote buffer file adapters only. */ private void startPreCacheIfNeeded() { if (preCacheThread != null) { @@ -729,7 +729,7 @@ public class BufferMgr { } /** - * Pre-cache source file into cache file. This is intended to be run in a + * Pre-cache source file into cache file. This is intended to be run in a * dedicated thread when the source file is remote. */ private void preCacheSourceFile() throws IOException { @@ -1038,6 +1038,12 @@ public class BufferMgr { */ private void handleCorruptionException(Exception exception, String errorText) throws IOException { + + if (exception instanceof ClosedException) { + // not a corruption exception, but rather it can happen when closing the database + throw (IOException) exception; + } + Msg.error(this, errorText, exception); corruptedState = true; if (exception instanceof IOException) { @@ -1651,8 +1657,7 @@ public class BufferMgr { monitor.checkCanceled(); if (index >= origIndexCount) { // Newly allocated free buffer - BufferNode node = - createNewBufferNode(index, currentCheckpointHead, null); + BufferNode node = createNewBufferNode(index, currentCheckpointHead, null); node.isDirty = true; node.modified = true; node.empty = true; diff --git a/Ghidra/Framework/Docking/src/main/java/docking/widgets/table/threaded/IncrementalLoadJob.java b/Ghidra/Framework/Docking/src/main/java/docking/widgets/table/threaded/IncrementalLoadJob.java index 8365e51883..188c5c1a23 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/widgets/table/threaded/IncrementalLoadJob.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/widgets/table/threaded/IncrementalLoadJob.java @@ -61,9 +61,8 @@ public class IncrementalLoadJob extends Job implements ThreadedTable doExecute(monitor); } catch (Exception e) { - // InterruptedException handled via notification below - if (!hasCause(e, InterruptedException.class)) { + if (!hasCause(e, InterruptedException.class) && !monitor.isCancelled()) { // TODO: is there a better way to handle exceptions? If we don't grab it and show // it here, then it will be handled by the Worker, which just prints it to the // console. Plus, handling it here gives us a chance to notify that the process is @@ -136,8 +135,7 @@ public class IncrementalLoadJob extends Job implements ThreadedTable // -A block on jobDone() can now complete as we release the lock // -jobDone() will notify listeners in an invokeLater(), which puts it behind ours // - Swing.runLater( - () -> updateManager.addThreadedTableListener(IncrementalLoadJob.this)); + Swing.runLater(() -> updateManager.addThreadedTableListener(IncrementalLoadJob.this)); } } @@ -192,12 +190,23 @@ public class IncrementalLoadJob extends Job implements ThreadedTable private class IncrementalUpdatingAccumulator extends SynchronizedListAccumulator { private volatile boolean cancelledOrDone; private Runnable runnable = () -> { + if (cancelledOrDone) { // this handles the case where a cancel request came in off the Swing // thread whilst we were already posted return; } - updateManager.reloadSpecificData(asList()); + try { + updateManager.reloadSpecificData(asList()); + } + catch (Exception e) { + + // note: check for cancelled again, as it may have been called after the initial + // check above if the cancel call was requested off the Swing thread. + if (!cancelledOrDone) { + Msg.error(this, "Exception incrementally loading table data", e); + } + } }; private SwingUpdateManager swingUpdateManager =