diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/Case.java b/Core/src/org/sleuthkit/autopsy/casemodule/Case.java index 55c0db7724..69d1efb0c4 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/Case.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/Case.java @@ -85,12 +85,12 @@ import org.sleuthkit.autopsy.core.UserPreferences; import org.sleuthkit.autopsy.core.UserPreferencesException; import org.sleuthkit.autopsy.corecomponentinterfaces.CoreComponentControl; import org.sleuthkit.autopsy.coreutils.DriveUtils; -import org.sleuthkit.autopsy.coreutils.ExecUtil; import org.sleuthkit.autopsy.coreutils.FileUtil; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil; import org.sleuthkit.autopsy.coreutils.NetworkUtils; import org.sleuthkit.autopsy.coreutils.PlatformUtil; +import org.sleuthkit.autopsy.coreutils.ThreadUtils; import org.sleuthkit.autopsy.coreutils.TimeZoneUtils; import org.sleuthkit.autopsy.coreutils.Version; import org.sleuthkit.autopsy.events.AutopsyEvent; @@ -129,7 +129,6 @@ public class Case { private static final String REPORTS_FOLDER = "Reports"; //NON-NLS private static final String TEMP_FOLDER = "Temp"; //NON-NLS private static final String MODULE_FOLDER = "ModuleOutput"; //NON-NLS - private static final long EXECUTOR_AWAIT_TIMEOUT_SECS = 5; private static final String CASE_ACTION_THREAD_NAME = "%s-case-action"; private static final String CASE_RESOURCES_THREAD_NAME = "%s-manage-case-resources"; private static final Logger logger = Logger.getLogger(Case.class.getName()); @@ -1646,7 +1645,7 @@ public class Case { } else { future.cancel(true); } - ExecUtil.shutDownTaskExecutor(caseLockingExecutor); + ThreadUtils.shutDownTaskExecutor(caseLockingExecutor); } catch (CancellationException discarded) { /* * The create/open task has been cancelled. Wait for it to finish, @@ -1655,7 +1654,7 @@ public class Case { * will have been closed and the case directory lock released will * have been released. */ - ExecUtil.shutDownTaskExecutor(caseLockingExecutor); + ThreadUtils.shutDownTaskExecutor(caseLockingExecutor); throw new CaseActionCancelledException(Bundle.Case_exceptionMessage_cancelledByUser()); } catch (ExecutionException ex) { /* @@ -1665,7 +1664,7 @@ public class Case { * case will have been closed and the case directory lock released * will have been released. */ - ExecUtil.shutDownTaskExecutor(caseLockingExecutor); + ThreadUtils.shutDownTaskExecutor(caseLockingExecutor); throw new CaseActionException(Bundle.Case_exceptionMessage_execExceptionWrapperMessage(ex.getCause().getLocalizedMessage()), ex); } finally { progressIndicator.finish(); @@ -1993,7 +1992,7 @@ public class Case { * would be possible to start the next task before the current * task responded to a cancellation request. */ - ExecUtil.shutDownTaskExecutor(executor); + ThreadUtils.shutDownTaskExecutor(executor); progressIndicator.finish(); } @@ -2064,7 +2063,7 @@ public class Case { } catch (ExecutionException ex) { throw new CaseActionException(Bundle.Case_exceptionMessage_execExceptionWrapperMessage(ex.getCause().getMessage()), ex); } finally { - ExecUtil.shutDownTaskExecutor(caseLockingExecutor); + ThreadUtils.shutDownTaskExecutor(caseLockingExecutor); progressIndicator.finish(); } } @@ -2175,7 +2174,7 @@ public class Case { Bundle.Case_servicesException_serviceResourcesCloseError(service.getServiceName(), ex.getLocalizedMessage()))); } } finally { - ExecUtil.shutDownTaskExecutor(executor); + ThreadUtils.shutDownTaskExecutor(executor); progressIndicator.finish(); } } diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/CaseEventListener.java b/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/CaseEventListener.java index 0f8c8512af..05f971a853 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/CaseEventListener.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/CaseEventListener.java @@ -42,7 +42,7 @@ import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationDataSource; import org.sleuthkit.autopsy.centralrepository.datamodel.EamDb; import org.sleuthkit.autopsy.centralrepository.datamodel.EamDbException; import org.sleuthkit.autopsy.centralrepository.datamodel.EamOrganization; -import org.sleuthkit.autopsy.coreutils.ExecUtil; +import org.sleuthkit.autopsy.coreutils.ThreadUtils; import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardArtifactTag; @@ -68,7 +68,7 @@ final class CaseEventListener implements PropertyChangeListener { } void shutdown() { - ExecUtil.shutDownTaskExecutor(jobProcessingExecutor); + ThreadUtils.shutDownTaskExecutor(jobProcessingExecutor); } @Override diff --git a/Core/src/org/sleuthkit/autopsy/coreutils/ExecUtil.java b/Core/src/org/sleuthkit/autopsy/coreutils/ExecUtil.java index 51163e502c..4c7c022871 100755 --- a/Core/src/org/sleuthkit/autopsy/coreutils/ExecUtil.java +++ b/Core/src/org/sleuthkit/autopsy/coreutils/ExecUtil.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2011-2016 Basis Technology Corp. + * Copyright 2011-2017 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -26,7 +26,6 @@ import java.io.InputStreamReader; import java.io.Writer; import java.util.Date; import java.util.List; -import java.util.concurrent.ExecutorService; import java.util.concurrent.TimeUnit; import java.util.logging.Level; import org.sleuthkit.autopsy.core.UserPreferences; @@ -213,40 +212,6 @@ public final class ExecUtil { } } - /** - * Shuts down a task executor service, waiting until all tasks are - * terminated. The current policy is to wait for the tasks to finish so that - * the case for which the executor is running can be left in a consistent - * state. - * - * @param executor The executor. - */ - public static void shutDownTaskExecutor(ExecutorService executor) { - executor.shutdown(); - boolean taskCompleted = false; - while (!taskCompleted) { - try { - taskCompleted = executor.awaitTermination(DEFAULT_TIMEOUT, DEFAULT_TIMEOUT_UNITS); - } catch (InterruptedException ignored) { - /* - * The current policy is to wait for the task to finish so that - * the case can be left in a consistent state. - * - * For a specific example of the motivation for this policy, - * note that a application service (Solr search service) - * experienced an error condition when opening case resources - * that left the service blocked uninterruptibly on a socket - * read. This eventually led to a mysterious "freeze" as the - * user-cancelled service task continued to run holdiong a lock - * that a UI thread soon tried to acquire. Thus it has been - * deemed better to make the "freeze" happen in a more - * informative way, i.e., with the progress indicator for the - * unfinished task on the screen, if a similar error condition - * arises again. - */ - } - } - } /** * EVERYTHING FOLLOWING THIS LINE IS DEPRECATED AND SLATED FOR REMOVAL */ diff --git a/Core/src/org/sleuthkit/autopsy/coreutils/ThreadUtils.java b/Core/src/org/sleuthkit/autopsy/coreutils/ThreadUtils.java new file mode 100644 index 0000000000..80f0467781 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/coreutils/ThreadUtils.java @@ -0,0 +1,67 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2011-2017 Basis Technology Corp. + * Contact: carrier sleuthkit org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.sleuthkit.autopsy.coreutils; + +import java.util.concurrent.ExecutorService; +import java.util.concurrent.TimeUnit; + +/* + * General purpose actions which can be performed on Threads. + */ +final public class ThreadUtils { + + private static final long DEFAULT_TIMEOUT = 5; + private static final TimeUnit DEFAULT_TIMEOUT_UNITS = TimeUnit.SECONDS; + + /** + * Shuts down a task executor service, waiting until all tasks are + * terminated. + * + * @param executor The executor. + */ + public static void shutDownTaskExecutor(ExecutorService executor) { + executor.shutdown(); + boolean taskCompleted = false; + while (!taskCompleted) { + try { + taskCompleted = executor.awaitTermination(DEFAULT_TIMEOUT, DEFAULT_TIMEOUT_UNITS); + } catch (InterruptedException ignored) { + /* + * The current policy is to wait for the task to finish so that + * the case can be left in a consistent state. + * + * For a specific example of the motivation for this policy, + * note that a application service (Solr search service) + * experienced an error condition when opening case resources + * that left the service blocked uninterruptibly on a socket + * read. This eventually led to a mysterious "freeze" as the + * user-cancelled service task continued to run holdiong a lock + * that a UI thread soon tried to acquire. Thus it has been + * deemed better to make the "freeze" happen in a more + * informative way, i.e., with the progress indicator for the + * unfinished task on the screen, if a similar error condition + * arises again. + */ + } + } + } + + private ThreadUtils() { + } +}