Fixed: Cannot properly cancel script searching

This commit is contained in:
Jindra Petřík
2021-02-12 11:08:07 +01:00
parent ab34d92351
commit 1bacb111fe
7 changed files with 54 additions and 10 deletions

View File

@@ -14,6 +14,7 @@ All notable changes to this project will be documented in this file.
- #1360 Precedence of increment/decrement operations
- #1407 NullPointer on Save as in BinaryData SWF subtree
- #1596 Infinite loop when sorting traits according to dependencies
- Cannot properly cancel script searching
## [13.0.2] - 2021-02-10
### Changed

View File

@@ -62,6 +62,7 @@ import java.util.Objects;
import java.util.Set;
import java.util.TreeSet;
import java.util.concurrent.Callable;
import java.util.concurrent.CancellationException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
@@ -255,14 +256,22 @@ public class ScriptPack extends AS3ClassTreeItem {
logger.log(Level.SEVERE, "Decompilation timeout", ex);
Helper.appendTimeoutCommentAs3(writer, timeout, 0);
return;
} catch (CancellationException ex) {
throw new InterruptedException();
} catch (ExecutionException ex) {
writer.continueMeasure();
Exception convertException = ex;
Throwable cause = ex.getCause();
if (ex instanceof ExecutionException && cause instanceof Exception) {
if (cause instanceof Exception) {
convertException = (Exception) cause;
}
if (convertException instanceof CancellationException) {
throw new InterruptedException();
}
if (convertException instanceof InterruptedException) {
throw (InterruptedException) convertException;
}
logger.log(Level.SEVERE, "Decompilation error", convertException);
Helper.appendErrorComment(writer, convertException);
return;

View File

@@ -52,6 +52,7 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.CancellationException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
@@ -326,9 +327,10 @@ public final class MethodBody implements Cloneable {
}
} catch (InterruptedException ex) {
throw ex;
} catch (CancellationException ex) {
throw new InterruptedException();
} catch (Exception | OutOfMemoryError | StackOverflowError ex) {
convertException = ex;
ex.printStackTrace();
Throwable cause = ex.getCause();
if (ex instanceof ExecutionException && cause instanceof Exception) {
convertException = (Exception) cause;

View File

@@ -12,7 +12,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library.
* License along with this library.
*/
package com.jpexs.decompiler.flash.search;
import com.jpexs.decompiler.flash.SWF;
@@ -26,8 +27,10 @@ import com.jpexs.decompiler.flash.helpers.HighlightedText;
import com.jpexs.decompiler.flash.helpers.HighlightedTextWriter;
import com.jpexs.decompiler.flash.tags.base.ASMSource;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CancellationException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.logging.Level;
@@ -114,7 +117,7 @@ public class ActionScriptSearch {
swf.getFlexMainClass(ignoredClasses, ignoredNss);
}
final List<ABCSearchResult> found = Collections.synchronizedList(new ArrayList<>());
List<ScriptPack> allpacks = swf.getAS3Packs();
final Pattern pat = regexp
? Pattern.compile(txt, ignoreCase ? (Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE) : 0)
@@ -168,6 +171,9 @@ public class ActionScriptSearch {
Future<HighlightedText> text = SWF.getCachedFuture(pack, new ScriptDecompiledListener<HighlightedText>() {
@Override
public void onStart() {
if (Thread.currentThread().isInterrupted()) {
return;
}
if (listener != null) {
listener.onDecompile(fpos, allpacks.size(), pack.getClassPath().toString());
}
@@ -175,8 +181,11 @@ public class ActionScriptSearch {
@Override
public void onComplete(HighlightedText result) {
public void onComplete(HighlightedText result) {
if (listener != null) {
if (!Thread.currentThread().isInterrupted()) {
if (listener != null) {
listener.onSearch(fpos, allpacks.size(), pack.getClassPath().toString());
}
}
if (pat.matcher(result.text).find()) {
@@ -193,6 +202,8 @@ public class ActionScriptSearch {
for (Future<HighlightedText> future : futures) {
try {
future.get();
} catch (CancellationException ex) {
throw new InterruptedException();
} catch (ExecutionException ex) {
Logger.getLogger(ActionScriptSearch.class.getName()).log(Level.SEVERE, null, ex);
}
@@ -205,7 +216,6 @@ public class ActionScriptSearch {
return found;
}
}
return null;
}
}

View File

@@ -12,12 +12,15 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library.
* License along with this library.
*/
package com.jpexs.helpers;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.WeakHashMap;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
@@ -42,11 +45,16 @@ public abstract class CancellableWorker<T> implements RunnableFuture<T> {
private final FutureTask<T> future;
private static final Map<Thread, CancellableWorker> threadWorkers = Collections.synchronizedMap(new WeakHashMap<>());
private List<CancellableWorker> subWorkers = Collections.synchronizedList(new ArrayList<>());
public CancellableWorker() {
super();
Callable<T> callable = new Callable<T>() {
@Override
public T call() throws Exception {
threadWorkers.put(Thread.currentThread(), CancellableWorker.this);
return doInBackground();
}
};
@@ -73,13 +81,22 @@ public abstract class CancellableWorker<T> implements RunnableFuture<T> {
protected void done() {
}
@SuppressWarnings("unchecked")
public final void execute() {
Thread t = Thread.currentThread();
if (threadWorkers.containsKey(t)) {
threadWorkers.get(t).subWorkers.add(this);
}
onStart();
THREAD_POOL.execute(this);
}
@Override
public final boolean cancel(boolean mayInterruptIfRunning) {
List<CancellableWorker> sw = new ArrayList<>(subWorkers);
for (CancellableWorker w : sw) {
w.cancel(mayInterruptIfRunning);
}
boolean r = future.cancel(mayInterruptIfRunning);
if (r) {
workerCancelled();
@@ -118,6 +135,10 @@ public abstract class CancellableWorker<T> implements RunnableFuture<T> {
}
public static <T> T call(final Callable<T> c, long timeout, TimeUnit timeUnit) throws InterruptedException, ExecutionException, TimeoutException {
Thread t = Thread.currentThread();
if (t.isInterrupted()) {
throw new InterruptedException();
}
CancellableWorker<T> worker = new CancellableWorker<T>() {
@Override

View File

@@ -1837,7 +1837,8 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se
Main.stopWork();
});
}
}
}.execute();
} else if (searchDialog.searchInTextsRadioButton.isSelected()) {
new CancellableWorker<Void>() {

View File

@@ -1118,7 +1118,7 @@ public class ABCPanel extends JPanel implements ItemListener, SearchListener<ABC
List<MultinameUsage> usages = abc.findMultinameDefinition(multinameIndex);
Multiname m = abc.constants.getMultiname(multinameIndex);
if (m == null){
if (m == null) {
return false;
}
//search other ABC tags if this is not private multiname