/*******************************************************************************
* Copyright (c) 2011 GigaSpaces Technologies Ltd. All rights reserved
*
* 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.cloudifysource.usm.shutdown;
import org.cloudifysource.usm.USMException;
import org.cloudifysource.usm.USMUtils;
import org.hyperic.sigar.Sigar;
import org.hyperic.sigar.SigarException;
import com.gigaspaces.internal.sigar.SigarHolder;
/**********
* The default process killer implementation, which uses SIGAR to kill processes.
*
* @author barakme
*
*/
public class DefaultProcessKiller implements ProcessKiller {
private static final int POST_KILL_SLEEP_INTERVAL = 100;
private static final int PROCESS_STATUS_CHECK_INTERVAL = 200;
private static final int PROCESS_STATUS_CHECK_ATTEMPTS = 5;
private static java.util.logging.Logger logger =
java.util.logging.Logger.getLogger(DefaultProcessKiller.class.getName());
private int killRetries = 2;
@Override
public void killProcess(final long pid)
throws USMException {
if (pid == 0) {
return; // this is possible in some end case situations, in the
// IntegratedProcessingUnitContainer
}
final Sigar sigar = SigarHolder.getSigar();
for (int retries = 0; retries <= killRetries; ++retries) {
try {
logger.info("Killing process: " + pid);
sigar.kill(pid, "SIGTERM"); // (9 is the only signal used for
// Kill on windows)
} catch (final SigarException e) {
logger.warning("Failed to shut down process: " + pid + ". Process may already be dead. Error was: "
+ e.getMessage() + ".");
}
try {
// sleep for a short period so process table get cleaned up
Thread.sleep(POST_KILL_SLEEP_INTERVAL);
} catch (final InterruptedException e1) {
// ignore
}
// wait until process dies
for (int i = 0; i < PROCESS_STATUS_CHECK_ATTEMPTS; ++i) {
if (!USMUtils.isProcessAlive(pid)) {
logger.info("Process " + pid + " is dead");
return;
}
try {
Thread.sleep(PROCESS_STATUS_CHECK_INTERVAL);
} catch (final InterruptedException e) {
// ignore
}
}
logger.warning("Attempt number " + (retries + 1) + " to kill process " + pid + " failed.");
}
logger.severe("Process " + pid + " did not die as expected!");
throw new USMException("Attempt to kill process " + pid + " failed!");
}
public int getKillRetries() {
return killRetries;
}
public void setKillRetries(final int killRetries) {
this.killRetries = killRetries;
}
}