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

@@ -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