Skip to content

Commit

Permalink
ZOOKEEPER-3620: Allow to override calls to System.exit in server side…
Browse files Browse the repository at this point in the history
… code

- Introduce a way to override calls to System.exit
- enable DM_EXIT spotbugs rule

see https://issues.apache.org/jira/browse/ZOOKEEPER-3620 for more context.

Author: Enrico Olivelli <enrico.olivelli@diennea.com>
Author: Enrico Olivelli <eolivelli@apache.org>

Reviewers: andor@apache.org

Closes apache#1147 from eolivelli/fix/ZOOKEEPER-3620-no-systemexit and squashes the following commits:

a234f85 [Enrico Olivelli] Fix checkstyle
4c4fec4 [Enrico Olivelli] Fix spotbugs warning
ae339b7 [Enrico Olivelli] Revert changes to VerGen.java
0e5ee07 [Enrico Olivelli] Enable DM_EXIT spotbugs rule for the full code base
b05a4bf [Enrico Olivelli] ZOOKEEPER-3620 Allow to override calls to System.exit in server side code: - Use a common utility to call System.exit - Override calls to System.exit to a NO-OP function in tests
  • Loading branch information
Enrico Olivelli authored and anmolnar committed Nov 28, 2019
1 parent 4132b64 commit 8e89050
Show file tree
Hide file tree
Showing 20 changed files with 139 additions and 41 deletions.
3 changes: 0 additions & 3 deletions excludeFindBugsFilter.xml
Expand Up @@ -7,8 +7,5 @@
<!-- this problem is to be addressed in ZOOKEEPER-3227 -->
<Bug pattern="DM_DEFAULT_ENCODING"/>

<!-- not really a problem -->
<Bug pattern="DM_EXIT"/>

</FindBugsFilter>

Expand Up @@ -20,6 +20,7 @@

import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import org.apache.zookeeper.server.ExitCode;
import org.apache.zookeeper.util.ServiceUtils;

public class Version implements org.apache.zookeeper.version.Info {

Expand Down Expand Up @@ -48,7 +49,7 @@ public static void printUsage() {
System.out.print("Usage:\tjava -cp ... org.apache.zookeeper.Version "
+ "[--full | --short | --revision],\n\tPrints --full version "
+ "info if no arg specified.");
System.exit(ExitCode.UNEXPECTED_ERROR.getValue());
ServiceUtils.requestSystemExit(ExitCode.UNEXPECTED_ERROR.getValue());
}

/**
Expand All @@ -68,7 +69,7 @@ public static void main(String[] args) {
}
if (args.length == 0 || (args.length == 1 && args[0].equals("--full"))) {
System.out.println(getFullVersion());
System.exit(ExitCode.EXECUTION_FINISHED.getValue());
ServiceUtils.requestSystemExit(ExitCode.EXECUTION_FINISHED.getValue());
}
if (args[0].equals("--short")) {
System.out.println(getVersion());
Expand All @@ -77,7 +78,7 @@ public static void main(String[] args) {
} else {
printUsage();
}
System.exit(ExitCode.EXECUTION_FINISHED.getValue());
ServiceUtils.requestSystemExit(ExitCode.EXECUTION_FINISHED.getValue());
}

}
Expand Up @@ -66,6 +66,7 @@
import org.apache.zookeeper.cli.VersionCommand;
import org.apache.zookeeper.client.ZKClientConfig;
import org.apache.zookeeper.server.ExitCode;
import org.apache.zookeeper.util.ServiceUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand Down Expand Up @@ -353,7 +354,7 @@ void run() throws CliException, IOException, InterruptedException {
// Command line args non-null. Run what was passed.
processCmd(cl);
}
System.exit(exitCode);
ServiceUtils.requestSystemExit(exitCode);
}

public void executeLine(String line) throws CliException, InterruptedException, IOException {
Expand Down Expand Up @@ -396,7 +397,7 @@ protected boolean processZKCmd(MyCommandOptions co) throws CliException, IOExcep

if (cmd.equals("quit")) {
zk.close();
System.exit(exitCode);
ServiceUtils.requestSystemExit(exitCode);
} else if (cmd.equals("redo") && args.length >= 2) {
Integer i = Integer.decode(args[1]);
if (commandCount <= i || i < 0) { // don't allow redoing this redo
Expand Down
Expand Up @@ -78,6 +78,7 @@
import org.apache.zookeeper.txn.SetDataTxn;
import org.apache.zookeeper.txn.Txn;
import org.apache.zookeeper.txn.TxnHeader;
import org.apache.zookeeper.util.ServiceUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand Down Expand Up @@ -301,7 +302,7 @@ public DataTree() {
childWatches = WatchManagerFactory.createWatchManager();
} catch (Exception e) {
LOG.error("Unexpected exception when creating WatchManager, exiting abnormally", e);
System.exit(ExitCode.UNEXPECTED_ERROR.getValue());
ServiceUtils.requestSystemExit(ExitCode.UNEXPECTED_ERROR.getValue());
}
}

Expand Down
Expand Up @@ -33,6 +33,7 @@
import org.apache.zookeeper.server.persistence.FileTxnLog;
import org.apache.zookeeper.server.util.SerializeUtils;
import org.apache.zookeeper.txn.TxnHeader;
import org.apache.zookeeper.util.ServiceUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand All @@ -51,13 +52,13 @@ public class LogFormatter {
public static void main(String[] args) throws Exception {
if (args.length != 1) {
System.err.println("USAGE: LogFormatter log_file");
System.exit(ExitCode.INVALID_INVOCATION.getValue());
ServiceUtils.requestSystemExit(ExitCode.INVALID_INVOCATION.getValue());
}

String error = ZKUtil.validateFileInput(args[0]);
if (null != error) {
System.err.println(error);
System.exit(ExitCode.INVALID_INVOCATION.getValue());
ServiceUtils.requestSystemExit(ExitCode.INVALID_INVOCATION.getValue());
}

FileInputStream fis = new FileInputStream(args[0]);
Expand All @@ -67,7 +68,7 @@ public static void main(String[] args) throws Exception {

if (fhdr.getMagic() != FileTxnLog.TXNLOG_MAGIC) {
System.err.println("Invalid magic number for " + args[0]);
System.exit(ExitCode.INVALID_INVOCATION.getValue());
ServiceUtils.requestSystemExit(ExitCode.INVALID_INVOCATION.getValue());
}
System.out.println("ZooKeeper Transactional Log File with dbid "
+ fhdr.getDbid()
Expand Down
Expand Up @@ -30,6 +30,7 @@
import org.apache.yetus.audience.InterfaceAudience;
import org.apache.zookeeper.server.persistence.FileTxnSnapLog;
import org.apache.zookeeper.server.persistence.Util;
import org.apache.zookeeper.util.ServiceUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand Down Expand Up @@ -230,7 +231,7 @@ private static int validateAndGetCount(String number) {

private static void printUsageThenExit() {
printUsage();
System.exit(ExitCode.UNEXPECTED_ERROR.getValue());
ServiceUtils.requestSystemExit(ExitCode.UNEXPECTED_ERROR.getValue());
}

}
Expand Up @@ -20,6 +20,7 @@

import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.util.concurrent.LinkedBlockingQueue;
import org.apache.zookeeper.util.ServiceUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand Down Expand Up @@ -257,7 +258,7 @@ public void shutdown() {
} catch (InterruptedException e) {
LOG.warn("Interrupted while waiting for {} to finish", this);
//TODO apply ZOOKEEPER-575 and remove this line.
System.exit(ExitCode.UNEXPECTED_ERROR.getValue());
ServiceUtils.requestSystemExit(ExitCode.UNEXPECTED_ERROR.getValue());
}
}

Expand Down
Expand Up @@ -35,6 +35,7 @@
import org.apache.zookeeper.server.persistence.FileSnap;
import org.apache.zookeeper.server.persistence.SnapStream;
import org.apache.zookeeper.server.persistence.Util;
import org.apache.zookeeper.util.ServiceUtils;
import org.json.simple.JSONValue;

/**
Expand Down Expand Up @@ -72,18 +73,19 @@ public static void main(String[] args) throws Exception {
System.err.println("USAGE: SnapshotFormatter [-d|-json] snapshot_file");
System.err.println(" -d dump the data for each znode");
System.err.println(" -json dump znode info in json format");
System.exit(ExitCode.INVALID_INVOCATION.getValue());
ServiceUtils.requestSystemExit(ExitCode.INVALID_INVOCATION.getValue());
return;
}

String error = ZKUtil.validateFileInput(snapshotFile);
if (null != error) {
System.err.println(error);
System.exit(ExitCode.INVALID_INVOCATION.getValue());
ServiceUtils.requestSystemExit(ExitCode.INVALID_INVOCATION.getValue());
}

if (dumpData && dumpJson) {
System.err.println("Cannot specify both data dump (-d) and json mode (-json) in same call");
System.exit(ExitCode.INVALID_INVOCATION.getValue());
ServiceUtils.requestSystemExit(ExitCode.INVALID_INVOCATION.getValue());
}

new SnapshotFormatter().run(snapshotFile, dumpData, dumpJson);
Expand Down
Expand Up @@ -25,6 +25,7 @@
import java.text.DateFormat;
import java.util.Date;
import org.apache.zookeeper.ZooDefs.OpCode;
import org.apache.zookeeper.util.ServiceUtils;

public class TraceFormatter {

Expand All @@ -35,7 +36,7 @@ public class TraceFormatter {
public static void main(String[] args) throws IOException {
if (args.length != 1) {
System.err.println("USAGE: TraceFormatter trace_file");
System.exit(ExitCode.INVALID_INVOCATION.getValue());
ServiceUtils.requestSystemExit(ExitCode.INVALID_INVOCATION.getValue());
}
FileChannel fc = new FileInputStream(args[0]).getChannel();
while (true) {
Expand Down
Expand Up @@ -80,6 +80,7 @@
import org.apache.zookeeper.server.util.RequestPathMetricsCollector;
import org.apache.zookeeper.txn.CreateSessionTxn;
import org.apache.zookeeper.txn.TxnHeader;
import org.apache.zookeeper.util.ServiceUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand Down Expand Up @@ -511,7 +512,7 @@ public void takeSnapshot(boolean syncSnap) {
LOG.error("Severe unrecoverable error, exiting", e);
// This is a severe error that we cannot recover from,
// so we need to exit
System.exit(ExitCode.TXNLOG_ERROR_TAKING_SNAPSHOT.getValue());
ServiceUtils.requestSystemExit(ExitCode.TXNLOG_ERROR_TAKING_SNAPSHOT.getValue());
}
long elapsed = Time.currentElapsedTime() - start;
LOG.info("Snapshot taken in {} ms", elapsed);
Expand Down
Expand Up @@ -35,6 +35,7 @@
import org.apache.zookeeper.server.persistence.FileTxnSnapLog.DatadirException;
import org.apache.zookeeper.server.quorum.QuorumPeerConfig.ConfigException;
import org.apache.zookeeper.server.util.JvmPauseMonitor;
import org.apache.zookeeper.util.ServiceUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand Down Expand Up @@ -69,29 +70,29 @@ public static void main(String[] args) {
LOG.info(USAGE);
System.err.println(USAGE);
ZKAuditProvider.addServerStartFailureAuditLog();
System.exit(ExitCode.INVALID_INVOCATION.getValue());
ServiceUtils.requestSystemExit(ExitCode.INVALID_INVOCATION.getValue());
} catch (ConfigException e) {
LOG.error("Invalid config, exiting abnormally", e);
System.err.println("Invalid config, exiting abnormally");
ZKAuditProvider.addServerStartFailureAuditLog();
System.exit(ExitCode.INVALID_INVOCATION.getValue());
ServiceUtils.requestSystemExit(ExitCode.INVALID_INVOCATION.getValue());
} catch (DatadirException e) {
LOG.error("Unable to access datadir, exiting abnormally", e);
System.err.println("Unable to access datadir, exiting abnormally");
ZKAuditProvider.addServerStartFailureAuditLog();
System.exit(ExitCode.UNABLE_TO_ACCESS_DATADIR.getValue());
ServiceUtils.requestSystemExit(ExitCode.UNABLE_TO_ACCESS_DATADIR.getValue());
} catch (AdminServerException e) {
LOG.error("Unable to start AdminServer, exiting abnormally", e);
System.err.println("Unable to start AdminServer, exiting abnormally");
ZKAuditProvider.addServerStartFailureAuditLog();
System.exit(ExitCode.ERROR_STARTING_ADMIN_SERVER.getValue());
ServiceUtils.requestSystemExit(ExitCode.ERROR_STARTING_ADMIN_SERVER.getValue());
} catch (Exception e) {
LOG.error("Unexpected exception, exiting abnormally", e);
ZKAuditProvider.addServerStartFailureAuditLog();
System.exit(ExitCode.UNEXPECTED_ERROR.getValue());
ServiceUtils.requestSystemExit(ExitCode.UNEXPECTED_ERROR.getValue());
}
LOG.info("Exiting normally");
System.exit(ExitCode.EXECUTION_FINISHED.getValue());
ServiceUtils.requestSystemExit(ExitCode.EXECUTION_FINISHED.getValue());
}

protected void initializeAndRun(String[] args) throws ConfigException, IOException, AdminServerException {
Expand Down
Expand Up @@ -58,6 +58,7 @@
import org.apache.zookeeper.txn.SetDataTxn;
import org.apache.zookeeper.txn.Txn;
import org.apache.zookeeper.txn.TxnHeader;
import org.apache.zookeeper.util.ServiceUtils;

public class TxnLogToolkit implements Closeable {

Expand Down Expand Up @@ -126,7 +127,7 @@ public static void main(String[] args) throws Exception {
printHelpAndExit(e.getExitCode(), e.getOptions());
} catch (TxnLogToolkitException e) {
System.err.println(e.getMessage());
System.exit(e.getExitCode());
ServiceUtils.requestSystemExit(e.getExitCode());
}
}

Expand Down Expand Up @@ -424,7 +425,7 @@ private static TxnLogToolkit parseCommandLine(String[] args) throws TxnLogToolki
private static void printHelpAndExit(int exitCode, Options options) {
HelpFormatter help = new HelpFormatter();
help.printHelp(120, "TxnLogToolkit [-dhrvc] <txn_log_file_name> (-z <zxid>)", "", options, "");
System.exit(exitCode);
ServiceUtils.requestSystemExit(exitCode);
}

private void printStat() {
Expand Down
Expand Up @@ -34,6 +34,7 @@
import org.apache.zookeeper.server.ZKDatabase;
import org.apache.zookeeper.server.persistence.FileTxnSnapLog;
import org.apache.zookeeper.txn.TxnHeader;
import org.apache.zookeeper.util.ServiceUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand Down Expand Up @@ -100,7 +101,7 @@ public void commit(long zxid) {
if (firstElementZxid != zxid) {
LOG.error("Committing zxid 0x" + Long.toHexString(zxid)
+ " but next pending txn 0x" + Long.toHexString(firstElementZxid));
System.exit(ExitCode.UNMATCHED_TXN_COMMIT.getValue());
ServiceUtils.requestSystemExit(ExitCode.UNMATCHED_TXN_COMMIT.getValue());
}
Request request = pendingTxns.remove();
request.logLatency(ServerMetrics.getMetrics().COMMIT_PROPAGATION_LATENCY);
Expand Down
Expand Up @@ -52,6 +52,7 @@
import org.apache.zookeeper.server.util.ZxidUtils;
import org.apache.zookeeper.txn.SetDataTxn;
import org.apache.zookeeper.txn.TxnHeader;
import org.apache.zookeeper.util.ServiceUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand Down Expand Up @@ -455,14 +456,13 @@ protected void syncWithLeader(long newLeaderZxid) throws Exception {
if (!truncated) {
// not able to truncate the log
LOG.error("Not able to truncate the log 0x{}", Long.toHexString(qp.getZxid()));
System.exit(ExitCode.QUORUM_PACKET_ERROR.getValue());
ServiceUtils.requestSystemExit(ExitCode.QUORUM_PACKET_ERROR.getValue());
}
zk.getZKDatabase().setlastProcessedZxid(qp.getZxid());

} else {
LOG.error("Got unexpected packet from leader: {}, exiting ... ", LearnerHandler.packetToString(qp));
System.exit(ExitCode.QUORUM_PACKET_ERROR.getValue());

ServiceUtils.requestSystemExit(ExitCode.QUORUM_PACKET_ERROR.getValue());
}
zk.getZKDatabase().initConfigInZKDatabase(self.getQuorumVerifier());
zk.createSessionTracker();
Expand Down
Expand Up @@ -55,6 +55,7 @@
import org.apache.zookeeper.server.quorum.flexible.QuorumVerifier;
import org.apache.zookeeper.server.util.ConfigUtils;
import org.apache.zookeeper.util.CircularBlockingQueue;
import org.apache.zookeeper.util.ServiceUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand Down Expand Up @@ -825,7 +826,7 @@ public class Listener extends ZooKeeperThread {
private static final int DEFAULT_PORT_BIND_MAX_RETRY = 3;

private final int portBindMaxRetry;
private Runnable socketBindErrorHandler = () -> System.exit(ExitCode.UNABLE_TO_BIND_QUORUM_PORT.getValue());
private Runnable socketBindErrorHandler = () -> ServiceUtils.requestSystemExit(ExitCode.UNABLE_TO_BIND_QUORUM_PORT.getValue());
volatile ServerSocket ss = null;

public Listener() {
Expand Down
Expand Up @@ -38,6 +38,7 @@
import org.apache.zookeeper.server.persistence.FileTxnSnapLog.DatadirException;
import org.apache.zookeeper.server.quorum.QuorumPeerConfig.ConfigException;
import org.apache.zookeeper.server.util.JvmPauseMonitor;
import org.apache.zookeeper.util.ServiceUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand Down Expand Up @@ -92,29 +93,29 @@ public static void main(String[] args) {
LOG.info(USAGE);
System.err.println(USAGE);
ZKAuditProvider.addServerStartFailureAuditLog();
System.exit(ExitCode.INVALID_INVOCATION.getValue());
ServiceUtils.requestSystemExit(ExitCode.INVALID_INVOCATION.getValue());
} catch (ConfigException e) {
LOG.error("Invalid config, exiting abnormally", e);
System.err.println("Invalid config, exiting abnormally");
ZKAuditProvider.addServerStartFailureAuditLog();
System.exit(ExitCode.INVALID_INVOCATION.getValue());
ServiceUtils.requestSystemExit(ExitCode.INVALID_INVOCATION.getValue());
} catch (DatadirException e) {
LOG.error("Unable to access datadir, exiting abnormally", e);
System.err.println("Unable to access datadir, exiting abnormally");
ZKAuditProvider.addServerStartFailureAuditLog();
System.exit(ExitCode.UNABLE_TO_ACCESS_DATADIR.getValue());
ServiceUtils.requestSystemExit(ExitCode.UNABLE_TO_ACCESS_DATADIR.getValue());
} catch (AdminServerException e) {
LOG.error("Unable to start AdminServer, exiting abnormally", e);
System.err.println("Unable to start AdminServer, exiting abnormally");
ZKAuditProvider.addServerStartFailureAuditLog();
System.exit(ExitCode.ERROR_STARTING_ADMIN_SERVER.getValue());
ServiceUtils.requestSystemExit(ExitCode.ERROR_STARTING_ADMIN_SERVER.getValue());
} catch (Exception e) {
LOG.error("Unexpected exception, exiting abnormally", e);
ZKAuditProvider.addServerStartFailureAuditLog();
System.exit(ExitCode.UNEXPECTED_ERROR.getValue());
ServiceUtils.requestSystemExit(ExitCode.UNEXPECTED_ERROR.getValue());
}
LOG.info("Exiting normally");
System.exit(ExitCode.EXECUTION_FINISHED.getValue());
ServiceUtils.requestSystemExit(ExitCode.EXECUTION_FINISHED.getValue());
}

protected void initializeAndRun(String[] args) throws ConfigException, IOException, AdminServerException {
Expand Down

0 comments on commit 8e89050

Please sign in to comment.