Skip to content

Commit fd2986b

Browse files
Alan Wangsmiklosovic
authored andcommitted
Added additional parameter to JVM shutdown to allow for logs to be properly shutdown
patch by Alan Wang; reviewed by Abe Ratnofsky, Caleb Rackliffe for CASSANDRA-20978
1 parent e1e39b0 commit fd2986b

File tree

8 files changed

+80
-5
lines changed

8 files changed

+80
-5
lines changed

CHANGES.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
5.1
2+
* Added additional parameter to JVM shutdown to allow for logs to be properly shutdown (CASSANDRA-20978)
23
* Improve isGossipOnlyMember and location lookup performance (CASSANDRA-21039)
34
* Refactor the way we check if a transformation is allowed to be committed during upgrades (CASSANDRA-21043)
45
* Improve debug around paused and disabled compaction (CASSANDRA-20131,CASSANDRA-19728)

src/java/org/apache/cassandra/service/DefaultDiskErrorsHandler.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ public void handleStartupFSError(Throwable t)
129129
logger.error("Exiting forcefully due to file system exception on startup, disk failure policy \"{}\"",
130130
DatabaseDescriptor.getDiskFailurePolicy(),
131131
t);
132-
JVMStabilityInspector.killCurrentJVM(t, true);
132+
JVMStabilityInspector.killCurrentJVM(t, true, true);
133133
break;
134134
default:
135135
break;
@@ -174,10 +174,10 @@ public void inspectCommitLogError(Throwable t)
174174
if (!StorageService.instance.isDaemonSetupCompleted())
175175
{
176176
logger.error("Exiting due to error while processing commit log during initialization.", t);
177-
JVMStabilityInspector.killCurrentJVM(t, true);
177+
JVMStabilityInspector.killCurrentJVM(t, true, true);
178178
}
179179
else if (DatabaseDescriptor.getCommitFailurePolicy() == Config.CommitFailurePolicy.die)
180-
JVMStabilityInspector.killCurrentJVM(t, false);
180+
JVMStabilityInspector.killCurrentJVM(t, false, true);
181181
}
182182

183183
private boolean shouldMaybeRemoveData(Throwable error)

src/java/org/apache/cassandra/utils/JVMStabilityInspector.java

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
import org.apache.cassandra.service.StorageService;
4848
import org.apache.cassandra.tracing.Tracing;
4949
import org.apache.cassandra.utils.concurrent.UncheckedInterruptedException;
50+
import org.apache.cassandra.utils.logging.LoggingSupportFactory;
5051

5152
import static org.apache.cassandra.config.CassandraRelevantProperties.PRINT_HEAP_HISTOGRAM_ON_OUT_OF_MEMORY_ERROR;
5253

@@ -226,16 +227,21 @@ public static void killCurrentJVM(Throwable t, boolean quiet)
226227
killer.killCurrentJVM(t, quiet);
227228
}
228229

230+
public static void killCurrentJVM(Throwable t, boolean quiet, boolean callShutDownOnLogger)
231+
{
232+
killer.killCurrentJVM(t, quiet, callShutDownOnLogger);
233+
}
234+
229235
public static void userFunctionTimeout(Throwable t)
230236
{
231237
switch (DatabaseDescriptor.getUserFunctionTimeoutPolicy())
232238
{
233239
case die:
234240
// policy to give 250ms grace time to
235-
ScheduledExecutors.nonPeriodicTasks.schedule(() -> killer.killCurrentJVM(t), 250, TimeUnit.MILLISECONDS);
241+
ScheduledExecutors.nonPeriodicTasks.schedule(() -> killer.killCurrentJVM(t, false, true), 250, TimeUnit.MILLISECONDS);
236242
break;
237243
case die_immediate:
238-
killer.killCurrentJVM(t);
244+
killer.killCurrentJVM(t, false, true);
239245
break;
240246
case ignore:
241247
logger.error(t.getMessage());
@@ -268,6 +274,11 @@ public void killCurrentJVM(Throwable t)
268274
}
269275

270276
public void killCurrentJVM(Throwable t, boolean quiet)
277+
{
278+
killCurrentJVM(t, quiet, false);
279+
}
280+
281+
public void killCurrentJVM(Throwable t, boolean quiet, boolean callShutDownOnLogger)
271282
{
272283
if (!quiet)
273284
{
@@ -279,6 +290,8 @@ public void killCurrentJVM(Throwable t, boolean quiet)
279290

280291
if (doExit && killing.compareAndSet(false, true))
281292
{
293+
if (callShutDownOnLogger)
294+
LoggingSupportFactory.getLoggingSupport().onShutdown();
282295
StorageService.instance.removeShutdownHook();
283296
System.exit(100);
284297
}

test/unit/org/apache/cassandra/cql3/OutOfSpaceTest.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ public void testFlushUnwriteableDie() throws Throwable
7979
flushAndExpectError();
8080
Assert.assertTrue(killerForTests.wasKilled());
8181
Assert.assertFalse(killerForTests.wasKilledQuietly()); //only killed quietly on startup failure
82+
Assert.assertFalse(killerForTests.calledShutDownOnLogger());
8283
}
8384
finally
8485
{

test/unit/org/apache/cassandra/db/commitlog/CommitLogFailurePolicyTest.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ public void testCommitFailurePolicy_die()
8383
CommitLog.handleCommitError("Testing die policy", new Throwable());
8484
Assert.assertTrue(killerForTests.wasKilled());
8585
Assert.assertFalse(killerForTests.wasKilledQuietly()); //only killed quietly on startup failure
86+
Assert.assertTrue(killerForTests.calledShutDownOnLogger());
8687
}
8788
finally
8889
{
@@ -108,6 +109,7 @@ public void testCommitFailurePolicy_ignore_beforeStartup()
108109
//even though policy is ignore, JVM must die because Daemon has not finished initializing
109110
Assert.assertTrue(killerForTests.wasKilled());
110111
Assert.assertTrue(killerForTests.wasKilledQuietly()); //killed quietly due to startup failure
112+
Assert.assertTrue(killerForTests.calledShutDownOnLogger());
111113
}
112114
finally
113115
{

test/unit/org/apache/cassandra/net/ResourceLimitsTest.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,7 @@ public void negativeConcurrentUsingValueKillsJVMTest()
173173
}
174174
Assert.assertTrue(killerForTests.wasKilled());
175175
Assert.assertFalse(killerForTests.wasKilledQuietly()); //only killed quietly on startup failure
176+
Assert.assertFalse(killerForTests.calledShutDownOnLogger());
176177
}
177178
finally
178179
{

test/unit/org/apache/cassandra/utils/JVMStabilityInspectorTest.java

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,48 @@ public void testKill() throws Exception
118118
}
119119
}
120120

121+
@Test
122+
public void testCallShutDownOnLoggerOnSpecificErrors() throws Exception
123+
{
124+
KillerForTests killerForTests = new KillerForTests();
125+
JVMStabilityInspector.Killer originalKiller = JVMStabilityInspector.replaceKiller(killerForTests);
126+
127+
Config.DiskFailurePolicy oldPolicy = DatabaseDescriptor.getDiskFailurePolicy();
128+
Config.UserFunctionTimeoutPolicy oldUserFunctionTimeoutPolicy = DatabaseDescriptor.getUserFunctionTimeoutPolicy();
129+
DiskErrorsHandlerService.configure();
130+
try
131+
{
132+
DatabaseDescriptor.setDiskFailurePolicy(Config.DiskFailurePolicy.die);
133+
killerForTests.reset();
134+
JVMStabilityInspector.inspectThrowable(new FSWriteError(new IOException(), "blah"));
135+
assertTrue(killerForTests.wasKilled());
136+
assertTrue(killerForTests.calledShutDownOnLogger());
137+
138+
killerForTests.reset();
139+
JVMStabilityInspector.inspectCommitLogThrowable(new Throwable());
140+
assertTrue(killerForTests.wasKilled());
141+
assertTrue(killerForTests.calledShutDownOnLogger());
142+
143+
DatabaseDescriptor.setUserFunctionTimeoutPolicy(Config.UserFunctionTimeoutPolicy.die_immediate);
144+
killerForTests.reset();
145+
JVMStabilityInspector.userFunctionTimeout(new Throwable());
146+
assertTrue(killerForTests.wasKilled());
147+
assertTrue(killerForTests.calledShutDownOnLogger());
148+
}
149+
catch (Exception | Error e)
150+
{
151+
throw new AssertionError("Failure when daemonSetupCompleted=false", e);
152+
}
153+
finally
154+
{
155+
JVMStabilityInspector.replaceKiller(originalKiller);
156+
DatabaseDescriptor.setDiskFailurePolicy(oldPolicy);
157+
DatabaseDescriptor.setUserFunctionTimeoutPolicy(oldUserFunctionTimeoutPolicy);
158+
StorageService.instance.registerDaemon(null);
159+
DiskErrorsHandlerService.set(DiskErrorsHandler.NoOpDiskErrorHandler.NO_OP);
160+
}
161+
}
162+
121163
@Test
122164
public void testOutOfMemoryHandling()
123165
{

test/unit/org/apache/cassandra/utils/KillerForTests.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ public class KillerForTests extends JVMStabilityInspector.Killer
2727
{
2828
private boolean killed = false;
2929
private boolean quiet = false;
30+
private boolean callShutDownOnLogger = false;
3031
private final boolean expected;
3132

3233
public KillerForTests()
@@ -41,6 +42,12 @@ public KillerForTests(boolean expectFailure)
4142

4243
@Override
4344
public void killCurrentJVM(Throwable t, boolean quiet)
45+
{
46+
killCurrentJVM(t, quiet, false);
47+
}
48+
49+
@Override
50+
public void killCurrentJVM(Throwable t, boolean quiet, boolean callShutDownOnLogger)
4451
{
4552
if (!expected)
4653
Assert.fail("Saw JVM Kill but did not expect it.");
@@ -52,6 +59,7 @@ public void killCurrentJVM(Throwable t, boolean quiet)
5259
}
5360
this.killed = true;
5461
this.quiet = quiet;
62+
this.callShutDownOnLogger = callShutDownOnLogger;
5563
}
5664

5765
public boolean wasKilled()
@@ -64,8 +72,15 @@ public boolean wasKilledQuietly()
6472
return quiet;
6573
}
6674

75+
public boolean calledShutDownOnLogger()
76+
{
77+
return callShutDownOnLogger;
78+
}
79+
6780
public void reset()
6881
{
6982
killed = false;
83+
quiet = false;
84+
callShutDownOnLogger = false;
7085
}
7186
}

0 commit comments

Comments
 (0)