Fork of Poseidon providing Bukkit #1060 to older Beta versions (b1.0-b1.7.3)
1package com.legacyminecraft.poseidon.watchdog;
2
3import com.legacyminecraft.poseidon.PoseidonConfig;
4
5import java.util.Arrays;
6import java.util.concurrent.atomic.AtomicBoolean;
7
8public class WatchDogThread extends Thread {
9 private int count = 0;
10 private Long lastTick = System.currentTimeMillis() / 1000L;
11 private volatile AtomicBoolean tickOccurred = new AtomicBoolean(true);
12 private Thread serverThread;
13 private final int killTimeout;
14 //Debug Timeout
15 private final boolean debugTimeoutEnabled;
16 private final int debugTimeout;
17 private boolean printedDebug;
18
19 public WatchDogThread(Thread thread) {
20 this.serverThread = thread;
21 this.killTimeout = PoseidonConfig.getInstance().getConfigInteger("settings.watchdog.timeout.value");
22
23 this.debugTimeoutEnabled = PoseidonConfig.getInstance().getConfigBoolean("settings.watchdog.debug-timeout.enabled");
24 this.debugTimeout = PoseidonConfig.getInstance().getConfigInteger("settings.watchdog.debug-timeout.value");
25 }
26
27 public void run() {
28 boolean running = true;
29 while (true && !this.isInterrupted() && running) {
30 try {
31 if (tickOccurred.get()) {
32 lastTick = System.currentTimeMillis() / 1000L;
33 tickOccurred.set(false);
34 printedDebug = false; //Set back tp false so if server hangs again debug is printed.
35 } else {
36 //Server timout check
37 if ((lastTick + killTimeout) < (System.currentTimeMillis() / 1000L)) {
38 System.out.println("[Poseidon-Watchdog] Server has hanged. Killing the process as a result of the watchdog timeout being exceeded.");
39 System.out.println("--------------------[Stacktrace For Developers]--------------------");
40 Arrays.asList(serverThread.getStackTrace()).forEach(System.out::println);
41 System.out.println("-------------------------------------------------------------------");
42 Runtime.getRuntime().halt(0);
43
44 } else {
45 System.out.println("[Poseidon-Watchdog] A server tick hasn't occurred in " + ((int) ((System.currentTimeMillis() / 1000L) - lastTick)) + " seconds.");
46 //Server debug timeout
47 if ((lastTick + debugTimeout) < (System.currentTimeMillis() / 1000L) && debugTimeoutEnabled && !printedDebug) {
48 System.out.println("[Poseidon-Watchdog] Server hang detected. Printing debug as debug timeout has been exceeded.");
49 System.out.println("--------------------[Stacktrace For Developers]--------------------");
50 Arrays.asList(serverThread.getStackTrace()).forEach(System.out::println);
51 System.out.println("-------------------------------------------------------------------");
52 printedDebug = true; //This variable prevents debug from printing multiple times during a single tick.
53 }
54 }
55 }
56 Thread.sleep(3000L);
57 } catch (InterruptedException e) {
58 System.out.println("[Poseidon-Watchdog] The watchdog has been interrupted.");
59// e.printStackTrace();
60 running = false;
61 }
62 }
63 }
64
65 public void tickUpdate() {
66 tickOccurred.set(true);
67 }
68
69 public boolean isHangDetected() {
70 return tickOccurred.get();
71 }
72}