This is an automated email from the ASF dual-hosted git repository.
andor pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/zookeeper.git
The following commit(s) were added to refs/heads/master by this push:
new 8e89050 ZOOKEEPER-3620: Allow to override calls to System.exit in
server side code
8e89050 is described below
commit 8e8905069f4bff670c0492fe9e28ced0f86bca00
Author: Enrico Olivelli <[email protected]>
AuthorDate: Thu Nov 28 12:24:36 2019 +0100
ZOOKEEPER-3620: Allow to override calls to System.exit in server side 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 <[email protected]>
Author: Enrico Olivelli <[email protected]>
Reviewers: [email protected]
Closes #1147 from eolivelli/fix/ZOOKEEPER-3620-no-systemexit and squashes
the following commits:
a234f85f1 [Enrico Olivelli] Fix checkstyle
4c4fec49e [Enrico Olivelli] Fix spotbugs warning
ae339b724 [Enrico Olivelli] Revert changes to VerGen.java
0e5ee07c5 [Enrico Olivelli] Enable DM_EXIT spotbugs rule for the full code
base
b05a4bf38 [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
---
excludeFindBugsFilter.xml | 3 -
.../main/java/org/apache/zookeeper/Version.java | 7 +-
.../java/org/apache/zookeeper/ZooKeeperMain.java | 5 +-
.../java/org/apache/zookeeper/server/DataTree.java | 3 +-
.../org/apache/zookeeper/server/LogFormatter.java | 7 +-
.../org/apache/zookeeper/server/PurgeTxnLog.java | 3 +-
.../apache/zookeeper/server/RequestThrottler.java | 3 +-
.../apache/zookeeper/server/SnapshotFormatter.java | 8 ++-
.../apache/zookeeper/server/TraceFormatter.java | 3 +-
.../apache/zookeeper/server/ZooKeeperServer.java | 3 +-
.../zookeeper/server/ZooKeeperServerMain.java | 13 ++--
.../server/persistence/TxnLogToolkit.java | 5 +-
.../server/quorum/FollowerZooKeeperServer.java | 3 +-
.../apache/zookeeper/server/quorum/Learner.java | 6 +-
.../zookeeper/server/quorum/QuorumCnxManager.java | 3 +-
.../zookeeper/server/quorum/QuorumPeerMain.java | 13 ++--
.../apache/zookeeper/server/util/LogChopper.java | 5 +-
.../org/apache/zookeeper/util/ServiceUtils.java | 77 ++++++++++++++++++++++
.../org/apache/zookeeper/version/util/VerGen.java | 4 +-
.../test/java/org/apache/zookeeper/ZKTestCase.java | 6 ++
20 files changed, 139 insertions(+), 41 deletions(-)
diff --git a/excludeFindBugsFilter.xml b/excludeFindBugsFilter.xml
index c836911..a296594 100644
--- a/excludeFindBugsFilter.xml
+++ b/excludeFindBugsFilter.xml
@@ -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>
diff --git a/zookeeper-server/src/main/java/org/apache/zookeeper/Version.java
b/zookeeper-server/src/main/java/org/apache/zookeeper/Version.java
index 181e463..4029c60 100644
--- a/zookeeper-server/src/main/java/org/apache/zookeeper/Version.java
+++ b/zookeeper-server/src/main/java/org/apache/zookeeper/Version.java
@@ -20,6 +20,7 @@ package org.apache.zookeeper;
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 {
@@ -48,7 +49,7 @@ public class Version implements
org.apache.zookeeper.version.Info {
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());
}
/**
@@ -68,7 +69,7 @@ public class Version implements
org.apache.zookeeper.version.Info {
}
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());
@@ -77,7 +78,7 @@ public class Version implements
org.apache.zookeeper.version.Info {
} else {
printUsage();
}
- System.exit(ExitCode.EXECUTION_FINISHED.getValue());
+ ServiceUtils.requestSystemExit(ExitCode.EXECUTION_FINISHED.getValue());
}
}
diff --git
a/zookeeper-server/src/main/java/org/apache/zookeeper/ZooKeeperMain.java
b/zookeeper-server/src/main/java/org/apache/zookeeper/ZooKeeperMain.java
index 857b16f..734cf7e 100644
--- a/zookeeper-server/src/main/java/org/apache/zookeeper/ZooKeeperMain.java
+++ b/zookeeper-server/src/main/java/org/apache/zookeeper/ZooKeeperMain.java
@@ -66,6 +66,7 @@ import org.apache.zookeeper.cli.SyncCommand;
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;
@@ -353,7 +354,7 @@ public class ZooKeeperMain {
// 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 {
@@ -396,7 +397,7 @@ public class ZooKeeperMain {
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
diff --git
a/zookeeper-server/src/main/java/org/apache/zookeeper/server/DataTree.java
b/zookeeper-server/src/main/java/org/apache/zookeeper/server/DataTree.java
index f370d88..0dc5458 100644
--- a/zookeeper-server/src/main/java/org/apache/zookeeper/server/DataTree.java
+++ b/zookeeper-server/src/main/java/org/apache/zookeeper/server/DataTree.java
@@ -78,6 +78,7 @@ import org.apache.zookeeper.txn.SetACLTxn;
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;
@@ -301,7 +302,7 @@ public class 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());
}
}
diff --git
a/zookeeper-server/src/main/java/org/apache/zookeeper/server/LogFormatter.java
b/zookeeper-server/src/main/java/org/apache/zookeeper/server/LogFormatter.java
index 459f802..e02a63d 100644
---
a/zookeeper-server/src/main/java/org/apache/zookeeper/server/LogFormatter.java
+++
b/zookeeper-server/src/main/java/org/apache/zookeeper/server/LogFormatter.java
@@ -33,6 +33,7 @@ import org.apache.zookeeper.server.persistence.FileHeader;
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;
@@ -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]);
@@ -67,7 +68,7 @@ public class LogFormatter {
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()
diff --git
a/zookeeper-server/src/main/java/org/apache/zookeeper/server/PurgeTxnLog.java
b/zookeeper-server/src/main/java/org/apache/zookeeper/server/PurgeTxnLog.java
index f7fbde3..0c92066 100644
---
a/zookeeper-server/src/main/java/org/apache/zookeeper/server/PurgeTxnLog.java
+++
b/zookeeper-server/src/main/java/org/apache/zookeeper/server/PurgeTxnLog.java
@@ -30,6 +30,7 @@ import java.util.Set;
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;
@@ -230,7 +231,7 @@ public class PurgeTxnLog {
private static void printUsageThenExit() {
printUsage();
- System.exit(ExitCode.UNEXPECTED_ERROR.getValue());
+ ServiceUtils.requestSystemExit(ExitCode.UNEXPECTED_ERROR.getValue());
}
}
diff --git
a/zookeeper-server/src/main/java/org/apache/zookeeper/server/RequestThrottler.java
b/zookeeper-server/src/main/java/org/apache/zookeeper/server/RequestThrottler.java
index 880ac49..16a1c6f 100644
---
a/zookeeper-server/src/main/java/org/apache/zookeeper/server/RequestThrottler.java
+++
b/zookeeper-server/src/main/java/org/apache/zookeeper/server/RequestThrottler.java
@@ -20,6 +20,7 @@ package org.apache.zookeeper.server;
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;
@@ -257,7 +258,7 @@ public class RequestThrottler extends
ZooKeeperCriticalThread {
} 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());
}
}
diff --git
a/zookeeper-server/src/main/java/org/apache/zookeeper/server/SnapshotFormatter.java
b/zookeeper-server/src/main/java/org/apache/zookeeper/server/SnapshotFormatter.java
index b3bf51b..a276ef3 100644
---
a/zookeeper-server/src/main/java/org/apache/zookeeper/server/SnapshotFormatter.java
+++
b/zookeeper-server/src/main/java/org/apache/zookeeper/server/SnapshotFormatter.java
@@ -35,6 +35,7 @@ import org.apache.zookeeper.data.StatPersisted;
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;
/**
@@ -72,18 +73,19 @@ public class SnapshotFormatter {
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);
diff --git
a/zookeeper-server/src/main/java/org/apache/zookeeper/server/TraceFormatter.java
b/zookeeper-server/src/main/java/org/apache/zookeeper/server/TraceFormatter.java
index 36a1e68..d1fd989 100644
---
a/zookeeper-server/src/main/java/org/apache/zookeeper/server/TraceFormatter.java
+++
b/zookeeper-server/src/main/java/org/apache/zookeeper/server/TraceFormatter.java
@@ -25,6 +25,7 @@ import java.nio.channels.FileChannel;
import java.text.DateFormat;
import java.util.Date;
import org.apache.zookeeper.ZooDefs.OpCode;
+import org.apache.zookeeper.util.ServiceUtils;
public class TraceFormatter {
@@ -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) {
diff --git
a/zookeeper-server/src/main/java/org/apache/zookeeper/server/ZooKeeperServer.java
b/zookeeper-server/src/main/java/org/apache/zookeeper/server/ZooKeeperServer.java
index 1e15f34..65be888 100644
---
a/zookeeper-server/src/main/java/org/apache/zookeeper/server/ZooKeeperServer.java
+++
b/zookeeper-server/src/main/java/org/apache/zookeeper/server/ZooKeeperServer.java
@@ -80,6 +80,7 @@ import org.apache.zookeeper.server.util.OSMXBean;
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;
@@ -511,7 +512,7 @@ public class ZooKeeperServer implements SessionExpirer,
ServerStats.Provider {
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);
diff --git
a/zookeeper-server/src/main/java/org/apache/zookeeper/server/ZooKeeperServerMain.java
b/zookeeper-server/src/main/java/org/apache/zookeeper/server/ZooKeeperServerMain.java
index 3b87312..7ddb1de 100644
---
a/zookeeper-server/src/main/java/org/apache/zookeeper/server/ZooKeeperServerMain.java
+++
b/zookeeper-server/src/main/java/org/apache/zookeeper/server/ZooKeeperServerMain.java
@@ -35,6 +35,7 @@ import org.apache.zookeeper.server.persistence.FileTxnSnapLog;
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;
@@ -69,29 +70,29 @@ public class ZooKeeperServerMain {
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 {
diff --git
a/zookeeper-server/src/main/java/org/apache/zookeeper/server/persistence/TxnLogToolkit.java
b/zookeeper-server/src/main/java/org/apache/zookeeper/server/persistence/TxnLogToolkit.java
index bb95d00..984fb03 100644
---
a/zookeeper-server/src/main/java/org/apache/zookeeper/server/persistence/TxnLogToolkit.java
+++
b/zookeeper-server/src/main/java/org/apache/zookeeper/server/persistence/TxnLogToolkit.java
@@ -58,6 +58,7 @@ import org.apache.zookeeper.txn.MultiTxn;
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 {
@@ -126,7 +127,7 @@ public class TxnLogToolkit implements Closeable {
printHelpAndExit(e.getExitCode(), e.getOptions());
} catch (TxnLogToolkitException e) {
System.err.println(e.getMessage());
- System.exit(e.getExitCode());
+ ServiceUtils.requestSystemExit(e.getExitCode());
}
}
@@ -424,7 +425,7 @@ public class TxnLogToolkit implements Closeable {
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() {
diff --git
a/zookeeper-server/src/main/java/org/apache/zookeeper/server/quorum/FollowerZooKeeperServer.java
b/zookeeper-server/src/main/java/org/apache/zookeeper/server/quorum/FollowerZooKeeperServer.java
index 4b786da..12e552f 100644
---
a/zookeeper-server/src/main/java/org/apache/zookeeper/server/quorum/FollowerZooKeeperServer.java
+++
b/zookeeper-server/src/main/java/org/apache/zookeeper/server/quorum/FollowerZooKeeperServer.java
@@ -34,6 +34,7 @@ import org.apache.zookeeper.server.SyncRequestProcessor;
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;
@@ -100,7 +101,7 @@ public class FollowerZooKeeperServer extends
LearnerZooKeeperServer {
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);
diff --git
a/zookeeper-server/src/main/java/org/apache/zookeeper/server/quorum/Learner.java
b/zookeeper-server/src/main/java/org/apache/zookeeper/server/quorum/Learner.java
index 515c0de..0896d88 100644
---
a/zookeeper-server/src/main/java/org/apache/zookeeper/server/quorum/Learner.java
+++
b/zookeeper-server/src/main/java/org/apache/zookeeper/server/quorum/Learner.java
@@ -52,6 +52,7 @@ import org.apache.zookeeper.server.util.SerializeUtils;
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;
@@ -455,14 +456,13 @@ public class Learner {
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();
diff --git
a/zookeeper-server/src/main/java/org/apache/zookeeper/server/quorum/QuorumCnxManager.java
b/zookeeper-server/src/main/java/org/apache/zookeeper/server/quorum/QuorumCnxManager.java
index e37986d..47a9ca9 100644
---
a/zookeeper-server/src/main/java/org/apache/zookeeper/server/quorum/QuorumCnxManager.java
+++
b/zookeeper-server/src/main/java/org/apache/zookeeper/server/quorum/QuorumCnxManager.java
@@ -55,6 +55,7 @@ import
org.apache.zookeeper.server.quorum.auth.QuorumAuthServer;
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;
@@ -825,7 +826,7 @@ public class QuorumCnxManager {
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() {
diff --git
a/zookeeper-server/src/main/java/org/apache/zookeeper/server/quorum/QuorumPeerMain.java
b/zookeeper-server/src/main/java/org/apache/zookeeper/server/quorum/QuorumPeerMain.java
index bf97488..054a47d 100644
---
a/zookeeper-server/src/main/java/org/apache/zookeeper/server/quorum/QuorumPeerMain.java
+++
b/zookeeper-server/src/main/java/org/apache/zookeeper/server/quorum/QuorumPeerMain.java
@@ -38,6 +38,7 @@ import org.apache.zookeeper.server.persistence.FileTxnSnapLog;
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;
@@ -92,29 +93,29 @@ public class QuorumPeerMain {
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 {
diff --git
a/zookeeper-server/src/main/java/org/apache/zookeeper/server/util/LogChopper.java
b/zookeeper-server/src/main/java/org/apache/zookeeper/server/util/LogChopper.java
index 3a07078..e0e52a9 100644
---
a/zookeeper-server/src/main/java/org/apache/zookeeper/server/util/LogChopper.java
+++
b/zookeeper-server/src/main/java/org/apache/zookeeper/server/util/LogChopper.java
@@ -36,6 +36,7 @@ import org.apache.zookeeper.server.ExitCode;
import org.apache.zookeeper.server.persistence.FileHeader;
import org.apache.zookeeper.server.persistence.FileTxnLog;
import org.apache.zookeeper.txn.TxnHeader;
+import org.apache.zookeeper.util.ServiceUtils;
/**
* this class will chop the log at the specified zxid
@@ -49,7 +50,7 @@ public class LogChopper {
System.out.println("Usage: LogChopper zxid_to_chop_to
txn_log_to_chop chopped_filename");
System.out.println(" this program will read the txn_log_to_chop
file and copy all the transactions");
System.out.println(" from it up to (and including) the given
zxid into chopped_filename.");
- System.exit(rc.getValue());
+ ServiceUtils.requestSystemExit(rc.getValue());
}
String txnLog = args[1];
String choppedLog = args[2];
@@ -63,7 +64,7 @@ public class LogChopper {
} catch (Exception e) {
System.out.println("Got exception: " + e.getMessage());
}
- System.exit(rc.getValue());
+ ServiceUtils.requestSystemExit(rc.getValue());
}
public static boolean chop(InputStream is, OutputStream os, long zxid)
throws IOException {
diff --git
a/zookeeper-server/src/main/java/org/apache/zookeeper/util/ServiceUtils.java
b/zookeeper-server/src/main/java/org/apache/zookeeper/util/ServiceUtils.java
new file mode 100644
index 0000000..68a25eb
--- /dev/null
+++ b/zookeeper-server/src/main/java/org/apache/zookeeper/util/ServiceUtils.java
@@ -0,0 +1,77 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.zookeeper.util;
+
+import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
+import java.util.Objects;
+import java.util.function.Consumer;
+import org.apache.zookeeper.server.ExitCode;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Utilities for service management.
+ */
+public abstract class ServiceUtils {
+
+ private static final Logger LOG =
LoggerFactory.getLogger(ServiceUtils.class);
+
+ private ServiceUtils() {
+ }
+
+ /**
+ * Default strategy for shutting down the JVM.
+ */
+ @SuppressFBWarnings("DM_EXIT")
+ public static final Consumer<Integer> SYSTEM_EXIT = (code) -> {
+ LOG.error("Exiting JVM with code {}", code);
+ System.exit(code);
+ };
+
+ /**
+ * No-op strategy, useful for tests.
+ */
+ public static final Consumer<Integer> LOG_ONLY = (code) -> {
+ LOG.error("Fatal error, JVM should exit with code {}. "
+ + "Actually System.exit is disabled", code);
+ };
+
+ private static Consumer<Integer> systemExitProcedure = SYSTEM_EXIT;
+
+ /**
+ * Override system callback. Useful for preventing the JVM to exit in tests
+ * or in applications that are running an in-process ZooKeeper server.
+ *
+ * @param systemExitProcedure
+ */
+ public static void setSystemExitProcedure(Consumer<Integer>
systemExitProcedure) {
+ Objects.requireNonNull(systemExitProcedure);
+ ServiceUtils.systemExitProcedure = systemExitProcedure;
+ }
+
+ /**
+ * Force shutdown of the JVM using System.exit.
+ *
+ * @param code the exit code
+ * @see ExitCode
+ */
+ public static void requestSystemExit(int code) {
+ systemExitProcedure.accept(code);
+ }
+
+}
diff --git
a/zookeeper-server/src/main/java/org/apache/zookeeper/version/util/VerGen.java
b/zookeeper-server/src/main/java/org/apache/zookeeper/version/util/VerGen.java
index c7f9fd9..3e9e62a 100644
---
a/zookeeper-server/src/main/java/org/apache/zookeeper/version/util/VerGen.java
+++
b/zookeeper-server/src/main/java/org/apache/zookeeper/version/util/VerGen.java
@@ -18,6 +18,7 @@
package org.apache.zookeeper.version.util;
+import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
@@ -25,6 +26,7 @@ import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.zookeeper.server.ExitCode;
+@SuppressFBWarnings("DM_EXIT")
public class VerGen {
private static final String PACKAGE_NAME = "org.apache.zookeeper.version";
@@ -123,7 +125,7 @@ public class VerGen {
w.write("}\n");
} catch (IOException e) {
System.out.println("Unable to generate version.VersionInfoMain
file: " + e.getMessage());
- System.exit(1);
+ System.exit(ExitCode.UNEXPECTED_ERROR.getValue());
}
}
diff --git
a/zookeeper-server/src/test/java/org/apache/zookeeper/ZKTestCase.java
b/zookeeper-server/src/test/java/org/apache/zookeeper/ZKTestCase.java
index d9d481a..78e3cd7 100644
--- a/zookeeper-server/src/test/java/org/apache/zookeeper/ZKTestCase.java
+++ b/zookeeper-server/src/test/java/org/apache/zookeeper/ZKTestCase.java
@@ -22,6 +22,7 @@ import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.io.File;
import java.time.LocalDateTime;
+import org.apache.zookeeper.util.ServiceUtils;
import org.junit.BeforeClass;
import org.junit.Rule;
import org.junit.rules.TestWatcher;
@@ -42,6 +43,11 @@ public class ZKTestCase {
protected static final File testBaseDir = new
File(System.getProperty("build.test.dir", "build"));
private static final Logger LOG =
LoggerFactory.getLogger(ZKTestCase.class);
+ static {
+ // Disable System.exit in tests.
+ ServiceUtils.setSystemExitProcedure(ServiceUtils.LOG_ONLY);
+ }
+
private String testName;
protected String getTestName() {