mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-03 09:49:23 +02:00
Fixed lockup in incremental load job when the latch was not counted down
This commit is contained in:
parent
c0cfad9107
commit
748d4d037f
2 changed files with 16 additions and 9 deletions
|
@ -35,10 +35,9 @@ public class IncrementalLoadJob<ROW_OBJECT> extends Job implements ThreadedTable
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used to signal that the updateManager has finished loading the final contents gathered
|
* Used to signal that the updateManager has finished loading the final contents gathered
|
||||||
* by this job. By default, the value is 0, which means there is nothing to wait for. If we
|
* by this job. This is also updated if this job is cancelled.
|
||||||
* flush, this will be set to 1.
|
|
||||||
*/
|
*/
|
||||||
private volatile CountDownLatch completedCallbackLatch = new CountDownLatch(0);
|
private volatile CountDownLatch completedCallbackLatch = new CountDownLatch(1);
|
||||||
private volatile boolean isCancelled = false;
|
private volatile boolean isCancelled = false;
|
||||||
private volatile IncrementalUpdatingAccumulator incrementalAccumulator;
|
private volatile IncrementalUpdatingAccumulator incrementalAccumulator;
|
||||||
|
|
||||||
|
@ -141,13 +140,18 @@ public class IncrementalLoadJob<ROW_OBJECT> extends Job implements ThreadedTable
|
||||||
// -A block on jobDone() can now complete as we release the lock
|
// -A block on jobDone() can now complete as we release the lock
|
||||||
// -jobDone() will notify listeners in an invokeLater(), which puts it behind ours
|
// -jobDone() will notify listeners in an invokeLater(), which puts it behind ours
|
||||||
//
|
//
|
||||||
completedCallbackLatch = new CountDownLatch(1);
|
|
||||||
Swing.runLater(() -> updateManager.addThreadedTableListener(IncrementalLoadJob.this));
|
Swing.runLater(() -> updateManager.addThreadedTableListener(IncrementalLoadJob.this));
|
||||||
}
|
}
|
||||||
|
|
||||||
waitForThreadedTableUpdateManagerToFinish();
|
waitForThreadedTableUpdateManagerToFinish();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Waits for the final flushed data to be added to the table. We will get called when the data
|
||||||
|
* is finished loading or cancelled. The latch will also be released if the cancel method of
|
||||||
|
* this job is called. This can happen if the work queue is told to cancel all jobs, which can
|
||||||
|
* happen if a new reload job is requested.
|
||||||
|
*/
|
||||||
private void waitForThreadedTableUpdateManagerToFinish() {
|
private void waitForThreadedTableUpdateManagerToFinish() {
|
||||||
try {
|
try {
|
||||||
completedCallbackLatch.await();
|
completedCallbackLatch.await();
|
||||||
|
@ -179,6 +183,7 @@ public class IncrementalLoadJob<ROW_OBJECT> extends Job implements ThreadedTable
|
||||||
super.cancel();
|
super.cancel();
|
||||||
isCancelled = true;
|
isCancelled = true;
|
||||||
incrementalAccumulator.cancel();
|
incrementalAccumulator.cancel();
|
||||||
|
completedCallbackLatch.countDown();
|
||||||
|
|
||||||
// Note: cannot do this here, since the cancel() call may happen asynchronously and after
|
// Note: cannot do this here, since the cancel() call may happen asynchronously and after
|
||||||
// a call to reload() on the table model. Assume that the model itself has already
|
// a call to reload() on the table model. Assume that the model itself has already
|
||||||
|
|
|
@ -56,7 +56,7 @@ import ghidra.util.task.TaskMonitor;
|
||||||
* <pre>
|
* <pre>
|
||||||
* {@literal QCallback<ITEM, RESULT> callback = new AbstractQCallback<ITEM, RESULT>()} {
|
* {@literal QCallback<ITEM, RESULT> callback = new AbstractQCallback<ITEM, RESULT>()} {
|
||||||
* public RESULT process(ITEM item, TaskMonitor monitor) {
|
* public RESULT process(ITEM item, TaskMonitor monitor) {
|
||||||
* // do work here...
|
* // do work here and create a RESULT item for later processing...
|
||||||
* }
|
* }
|
||||||
* };
|
* };
|
||||||
*
|
*
|
||||||
|
@ -85,7 +85,7 @@ import ghidra.util.task.TaskMonitor;
|
||||||
* <pre>{@literal
|
* <pre>{@literal
|
||||||
* QCallback<ITEM, RESULT> callback = new AbstractQCallback<ITEM, RESULT>() {
|
* QCallback<ITEM, RESULT> callback = new AbstractQCallback<ITEM, RESULT>() {
|
||||||
* public RESULT process(ITEM item, TaskMonitor monitor) {
|
* public RESULT process(ITEM item, TaskMonitor monitor) {
|
||||||
* // do work here...
|
* // do work here and create a RESULT item for later processing...
|
||||||
* }
|
* }
|
||||||
* };}
|
* };}
|
||||||
*
|
*
|
||||||
|
@ -652,6 +652,7 @@ public class ConcurrentQ<I, R> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Called by the FutureTaskMonitor that we gave to the thread pool
|
||||||
private class CallbackCallable implements Callable<R> {
|
private class CallbackCallable implements Callable<R> {
|
||||||
|
|
||||||
private I item;
|
private I item;
|
||||||
|
@ -663,6 +664,7 @@ public class ConcurrentQ<I, R> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public R call() throws Exception {
|
public R call() throws Exception {
|
||||||
|
// callback is the client callback given to this queue at construction
|
||||||
return callback.process(item, future);
|
return callback.process(item, future);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue