Skip to content

Commit

Permalink
Add a non-daemon thread. (#9642)
Browse files Browse the repository at this point in the history
Signed-off-by: Cody Littley <cody@swirldslabs.com>
  • Loading branch information
cody-littley committed Nov 2, 2023
1 parent 12414d9 commit b1b815d
Show file tree
Hide file tree
Showing 3 changed files with 91 additions and 12 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
/*
* Copyright (C) 2023 Hedera Hashgraph, LLC
*
* Licensed 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 com.swirlds.platform;

import static java.util.concurrent.TimeUnit.SECONDS;

import com.swirlds.base.state.Startable;
import com.swirlds.base.state.Stoppable;
import com.swirlds.common.threading.framework.config.ThreadConfiguration;
import com.swirlds.common.threading.manager.ThreadManager;
import edu.umd.cs.findbugs.annotations.NonNull;

/**
* Creates a non-daemon JVM thread that does nothing. Keeps the JVM alive if all other threads are daemon threads.
*/
public class JvmAnchor implements Startable, Stoppable {

private final Thread thread;

/**
* Constructor.
*
* @param threadManager the thread manager
*/
public JvmAnchor(@NonNull final ThreadManager threadManager) {
thread = new ThreadConfiguration(threadManager)
.setComponent("platform")
.setThreadName("jvm-anchor")
.setRunnable(this::run)
.setDaemon(false)
.build();
}

/**
* {@inheritDoc}
*/
@Override
public void start() {
thread.start();
}

/**
* {@inheritDoc}
*/
@Override
public void stop() {
thread.interrupt();
}

/**
* Runs and does nothing until interrupted.
*/
private void run() {
while (!Thread.currentThread().isInterrupted()) {
try {
SECONDS.sleep(Integer.MAX_VALUE);
} catch (final InterruptedException e) {
Thread.currentThread().interrupt();
return;
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -737,6 +737,10 @@ public class SwirldsPlatform implements Platform {
Pair.of(consensusRoundHandler, "consensusRoundHandler"),
Pair.of(transactionPool, "transactionPool")));

if (platformContext.getConfiguration().getConfigData(ThreadConfig.class).jvmAnchor()) {
components.add(new JvmAnchor(threadManager));
}

// To be removed once the GUI component is better integrated with the platform.
GuiPlatformAccessor.getInstance().setShadowGraph(selfId, shadowGraph);
GuiPlatformAccessor.getInstance().setStateManagementComponent(selfId, stateManagementComponent);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,22 +24,20 @@
/**
* Thread related config
*
* @param logStackTracePauseDuration
* If a thread takes longer than this duration to {@link StoppableThread#pause()}, log a stack trace for debugging
* purposes. A value of {@link Duration#ZERO} means never log.
* @param threadPrioritySync
* priority for threads that sync (in SyncCaller, SyncListener, SyncServer)
* @param threadPriorityNonSync
* priority for threads that don't sync (all but SyncCaller, SyncListener,SyncServer)
* @param threadDumpPeriodMs
* period of generating thread dump file in the unit of milliseconds
* @param threadDumpLogDir
* thread dump files will be generated in this directory
* @param logStackTracePauseDuration If a thread takes longer than this duration to {@link StoppableThread#pause()}, log
* a stack trace for debugging purposes. A value of {@link Duration#ZERO} means never
* log.
* @param threadPrioritySync priority for threads that sync (in SyncCaller, SyncListener, SyncServer)
* @param threadPriorityNonSync priority for threads that don't sync (all but SyncCaller, SyncListener,SyncServer)
* @param threadDumpPeriodMs period of generating thread dump file in the unit of milliseconds
* @param threadDumpLogDir thread dump files will be generated in this directory
* @param jvmAnchor if true then create a non-daemon thread that will keep the JVM alive
*/
@ConfigData("thread")
public record ThreadConfig(
@ConfigProperty(defaultValue = "5s") Duration logStackTracePauseDuration,
@ConfigProperty(defaultValue = "5") int threadPrioritySync,
@ConfigProperty(defaultValue = "5") int threadPriorityNonSync,
@ConfigProperty(defaultValue = "0") long threadDumpPeriodMs,
@ConfigProperty(defaultValue = "data/threadDump") String threadDumpLogDir) {}
@ConfigProperty(defaultValue = "data/threadDump") String threadDumpLogDir,
@ConfigProperty(defaultValue = "true") boolean jvmAnchor) {}

0 comments on commit b1b815d

Please sign in to comment.