package com.metrink.croquet;
import java.io.File;
import java.io.IOException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Manages pid files.
*/
class PidManager {
private static final Logger LOG = LoggerFactory.getLogger(PidManager.class);
private static final String PID_FILENAME = "croquet.pid";
private String pidFilename;
/**
* Default constructor.
*/
PidManager() {
this.pidFilename = PID_FILENAME;
}
/**
* Initialize the instance.
* @param pidFilename the name of the pid file
*/
PidManager(final String pidFilename) {
this.pidFilename = pidFilename;
}
/**
* Wrapper around {@link #dropPidFile()}. If the call is unsuccessful, terminate the JVM.
*/
void dropPidOrDie() {
if (!dropPidFile()) {
LOG.error("Pid file {} already exists... exiting.", pidFilename);
// print to the console as well
System.err.println("Pid file already exists... exiting.");
System.err.flush();
System.exit(-1);
}
}
/**
* Create a file with the current process id in it. This is a no-op on Windows. Prior copies of the file must be
* removed prior to launch.
* @return true if the pid file was successfully created
*/
private boolean dropPidFile() {
LOG.trace("Entering dropPidFile()");
// we cannot create pid files on Windows
if (System.getProperty("os.name").startsWith("Windows")) {
LOG.info("Pid file creation is unsupported on Windows... skipping");
return true;
}
try {
final String[] cmd = {"bash", "-o", "noclobber", "-c", "echo $PPID > " + pidFilename};
final Process p = Runtime.getRuntime().exec(cmd);
if (p.waitFor() != 0) {
LOG.error("Unable to drop PID file");
return false;
}
} catch (final InterruptedException | IOException e) {
LOG.error("Unable to drop PID file: " + e.getMessage());
return false;
}
// This must be called after we've successfully dropped the PID file. Otherwise, it might clean-up another
// instances PID file. Keep in mind this doesn't account for kill -9 or a hard lockup. The start-up script
// should provide some additional logic to clean-up stale pid files.
new File(pidFilename).deleteOnExit();
LOG.debug("Dropped PID file");
LOG.trace("Exiting dropPIDFile()");
return true;
}
}