Skip to content

Commit 7e4f778

Browse files
committed
[server] Register signal handlers to log termination due to SIGTERM, SIGHUP and SIGINT
1 parent ae84521 commit 7e4f778

File tree

4 files changed

+248
-1
lines changed

4 files changed

+248
-1
lines changed

fluss-server/src/main/java/org/apache/fluss/server/ServerBase.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
import org.apache.fluss.server.utils.ConfigurationParserUtils;
3333
import org.apache.fluss.server.utils.FatalErrorHandler;
3434
import org.apache.fluss.server.utils.ShutdownHookUtil;
35+
import org.apache.fluss.server.utils.SignalHandler;
3536
import org.apache.fluss.utils.AutoCloseableAsync;
3637
import org.apache.fluss.utils.ExceptionUtils;
3738
import org.apache.fluss.utils.concurrent.FutureUtils;
@@ -113,6 +114,7 @@ protected static void startServer(ServerBase server) {
113114
}
114115

115116
public void start() throws Exception {
117+
SignalHandler.register(LOG);
116118
try {
117119
addShutDownHook();
118120

fluss-server/src/main/java/org/apache/fluss/server/tablet/TabletServer.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -284,7 +284,7 @@ protected void startServices() throws Exception {
284284
@Override
285285
protected CompletableFuture<Result> closeAsync(Result result) {
286286
if (isShutDown.compareAndSet(false, true)) {
287-
287+
LOG.info("Shutting down Tablet server ({}).", result);
288288
controlledShutDown();
289289

290290
CompletableFuture<Void> serviceShutdownFuture = stopServices();
Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
package org.apache.fluss.server.utils;
19+
20+
import org.apache.fluss.annotation.Internal;
21+
22+
/** An enumeration indicating the operating system that the JVM runs on. */
23+
@Internal
24+
public enum OperatingSystem {
25+
LINUX,
26+
WINDOWS,
27+
MAC_OS,
28+
FREE_BSD,
29+
SOLARIS,
30+
UNKNOWN;
31+
32+
// ------------------------------------------------------------------------
33+
34+
/**
35+
* Gets the operating system that the JVM runs on from the java system properties. this method
36+
* returns <tt>UNKNOWN</tt>, if the operating system was not successfully determined.
37+
*
38+
* @return The enum constant for the operating system, or <tt>UNKNOWN</tt>, if it was not
39+
* possible to determine.
40+
*/
41+
public static OperatingSystem getCurrentOperatingSystem() {
42+
return os;
43+
}
44+
45+
/**
46+
* Checks whether the operating system this JVM runs on is Windows.
47+
*
48+
* @return <code>true</code> if the operating system this JVM runs on is Windows, <code>false
49+
* </code> otherwise
50+
*/
51+
public static boolean isWindows() {
52+
return getCurrentOperatingSystem() == WINDOWS;
53+
}
54+
55+
/**
56+
* Checks whether the operating system this JVM runs on is Linux.
57+
*
58+
* @return <code>true</code> if the operating system this JVM runs on is Linux, <code>false
59+
* </code> otherwise
60+
*/
61+
public static boolean isLinux() {
62+
return getCurrentOperatingSystem() == LINUX;
63+
}
64+
65+
/**
66+
* Checks whether the operating system this JVM runs on is Windows.
67+
*
68+
* @return <code>true</code> if the operating system this JVM runs on is Windows, <code>false
69+
* </code> otherwise
70+
*/
71+
public static boolean isMac() {
72+
return getCurrentOperatingSystem() == MAC_OS;
73+
}
74+
75+
/**
76+
* Checks whether the operating system this JVM runs on is FreeBSD.
77+
*
78+
* @return <code>true</code> if the operating system this JVM runs on is FreeBSD, <code>false
79+
* </code> otherwise
80+
*/
81+
public static boolean isFreeBSD() {
82+
return getCurrentOperatingSystem() == FREE_BSD;
83+
}
84+
85+
/**
86+
* Checks whether the operating system this JVM runs on is Solaris.
87+
*
88+
* @return <code>true</code> if the operating system this JVM runs on is Solaris, <code>false
89+
* </code> otherwise
90+
*/
91+
public static boolean isSolaris() {
92+
return getCurrentOperatingSystem() == SOLARIS;
93+
}
94+
95+
/** The enum constant for the operating system. */
96+
private static final OperatingSystem os = readOSFromSystemProperties();
97+
98+
/**
99+
* Parses the operating system that the JVM runs on from the java system properties. If the
100+
* operating system was not successfully determined, this method returns {@code UNKNOWN}.
101+
*
102+
* @return The enum constant for the operating system, or {@code UNKNOWN}, if it was not
103+
* possible to determine.
104+
*/
105+
private static OperatingSystem readOSFromSystemProperties() {
106+
String osName = System.getProperty(OS_KEY);
107+
108+
if (osName.startsWith(LINUX_OS_PREFIX)) {
109+
return LINUX;
110+
}
111+
if (osName.startsWith(WINDOWS_OS_PREFIX)) {
112+
return WINDOWS;
113+
}
114+
if (osName.startsWith(MAC_OS_PREFIX)) {
115+
return MAC_OS;
116+
}
117+
if (osName.startsWith(FREEBSD_OS_PREFIX)) {
118+
return FREE_BSD;
119+
}
120+
String osNameLowerCase = osName.toLowerCase();
121+
if (osNameLowerCase.contains(SOLARIS_OS_INFIX_1)
122+
|| osNameLowerCase.contains(SOLARIS_OS_INFIX_2)) {
123+
return SOLARIS;
124+
}
125+
126+
return UNKNOWN;
127+
}
128+
129+
// --------------------------------------------------------------------------------------------
130+
// Constants to extract the OS type from the java environment
131+
// --------------------------------------------------------------------------------------------
132+
133+
/** The key to extract the operating system name from the system properties. */
134+
private static final String OS_KEY = "os.name";
135+
136+
/** The expected prefix for Linux operating systems. */
137+
private static final String LINUX_OS_PREFIX = "Linux";
138+
139+
/** The expected prefix for Windows operating systems. */
140+
private static final String WINDOWS_OS_PREFIX = "Windows";
141+
142+
/** The expected prefix for Mac OS operating systems. */
143+
private static final String MAC_OS_PREFIX = "Mac";
144+
145+
/** The expected prefix for FreeBSD. */
146+
private static final String FREEBSD_OS_PREFIX = "FreeBSD";
147+
148+
/** One expected infix for Solaris. */
149+
private static final String SOLARIS_OS_INFIX_1 = "sunos";
150+
151+
/** One expected infix for Solaris. */
152+
private static final String SOLARIS_OS_INFIX_2 = "solaris";
153+
}
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
package org.apache.fluss.server.utils;
19+
20+
import org.slf4j.Logger;
21+
import sun.misc.Signal;
22+
23+
/**
24+
* This signal handler / signal logger is based on Apache Hadoop's
25+
* org.apache.hadoop.util.SignalLogger.
26+
*/
27+
public class SignalHandler {
28+
29+
private static boolean registered = false;
30+
31+
/** Our signal handler. */
32+
private static class Handler implements sun.misc.SignalHandler {
33+
34+
private final Logger LOG;
35+
private final sun.misc.SignalHandler prevHandler;
36+
37+
Handler(String name, Logger LOG) {
38+
this.LOG = LOG;
39+
prevHandler = Signal.handle(new Signal(name), this);
40+
}
41+
42+
/**
43+
* Handle an incoming signal.
44+
*
45+
* @param signal The incoming signal
46+
*/
47+
@Override
48+
public void handle(Signal signal) {
49+
LOG.warn(
50+
"RECEIVED SIGNAL {}: SIG{}. Shutting down as requested.",
51+
signal.getNumber(),
52+
signal.getName());
53+
prevHandler.handle(signal);
54+
}
55+
}
56+
57+
/**
58+
* Register some signal handlers.
59+
*
60+
* @param LOG The slf4j logger
61+
*/
62+
public static void register(final Logger LOG) {
63+
synchronized (SignalHandler.class) {
64+
if (registered) {
65+
return;
66+
}
67+
registered = true;
68+
69+
final String[] SIGNALS =
70+
OperatingSystem.isWindows()
71+
? new String[] {"TERM", "INT"}
72+
: new String[] {"TERM", "HUP", "INT"};
73+
74+
StringBuilder bld = new StringBuilder();
75+
bld.append("Registered UNIX signal handlers for [");
76+
77+
String separator = "";
78+
for (String signalName : SIGNALS) {
79+
try {
80+
new Handler(signalName, LOG);
81+
bld.append(separator);
82+
bld.append(signalName);
83+
separator = ", ";
84+
} catch (Exception e) {
85+
LOG.info("Error while registering signal handler", e);
86+
}
87+
}
88+
bld.append("]");
89+
LOG.info(bld.toString());
90+
}
91+
}
92+
}

0 commit comments

Comments
 (0)