/******************************************************************************* * Copyright (c) 2013 Rene Schneider, GEBIT Solutions GmbH and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html *******************************************************************************/ package de.gebit.integrity.runner.forking.processes; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import com.google.inject.Singleton; import de.gebit.integrity.runner.forking.Fork; /** * The standard process terminator implementation. * * @author Rene Schneider - initial API and implementation * */ @Singleton public class DefaultProcessTerminator implements ProcessTerminator { /** * List of all known forks. */ protected List<Fork> forks = new ArrayList<Fork>(); /** * List of all known generic processes. */ protected List<Process> processes = new ArrayList<Process>(); /** * We need to ignore deregistrations from outside during kill phases. */ protected boolean ignoreDeregistrations; @Override public void registerFork(Fork aFork) { synchronized (forks) { if (!forks.contains(aFork)) { forks.add(aFork); } } } @Override public void unregisterFork(Fork aFork) { if (ignoreDeregistrations) { return; } synchronized (forks) { forks.remove(aFork); } } @Override public void registerProcess(Process aProcess) { synchronized (processes) { if (!processes.contains(aProcess)) { processes.add(aProcess); } } } @Override public void unregisterProcess(Process aProcess) { if (ignoreDeregistrations) { return; } synchronized (processes) { processes.remove(aProcess); } } @Override public boolean killAndWait(int aTimeout) { Thread tempKillThread = new Thread("Integrity - Process Terminator Thread") { @Override public void run() { try { ignoreDeregistrations = true; synchronized (forks) { Iterator<Fork> tempForkIterator = forks.iterator(); while (tempForkIterator.hasNext()) { Fork tempFork = tempForkIterator.next(); try { tempFork.kill(); tempForkIterator.remove(); } catch (InterruptedException exc) { exc.printStackTrace(); return; } } } synchronized (processes) { Iterator<Process> tempProcessIterator = processes.iterator(); while (tempProcessIterator.hasNext()) { try { Process tempProcess = tempProcessIterator.next(); tempProcess.destroy(); tempProcess.waitFor(); tempProcessIterator.remove(); } catch (InterruptedException exc) { exc.printStackTrace(); return; } } } } finally { ignoreDeregistrations = false; } } }; tempKillThread.start(); try { tempKillThread.join(aTimeout); if (tempKillThread.isAlive()) { tempKillThread.interrupt(); } } catch (InterruptedException exc) { exc.printStackTrace(); } return forks.size() + processes.size() == 0; } }