From 7639a6ad467bf7f3874d3cd4e875cdb6cce3e965 Mon Sep 17 00:00:00 2001 From: Lixfel Date: Fri, 13 May 2022 20:47:02 +0200 Subject: [PATCH] New 1.18 crash detector --- .../src/de/steamwar/core/Core.java | 5 ++ .../src/de/steamwar/core/CrashDetector.java | 64 +++++++++++++++++++ 2 files changed, 69 insertions(+) create mode 100644 SpigotCore_Main/src/de/steamwar/core/CrashDetector.java diff --git a/SpigotCore_Main/src/de/steamwar/core/Core.java b/SpigotCore_Main/src/de/steamwar/core/Core.java index 1ef9272..5bc007c 100644 --- a/SpigotCore_Main/src/de/steamwar/core/Core.java +++ b/SpigotCore_Main/src/de/steamwar/core/Core.java @@ -84,6 +84,7 @@ public class Core extends JavaPlugin{ } private ErrorHandler errorHandler; + private CrashDetector crashDetector; @Override public void onLoad() { @@ -94,6 +95,8 @@ public class Core extends JavaPlugin{ public void onEnable() { setSqlConfig(); errorHandler = new ErrorHandler(); + if(VERSION > 15) + crashDetector = new CrashDetector(); Bukkit.getPluginManager().registerEvents(new PlayerJoinedEvent(), this); Bukkit.getPluginManager().registerEvents(new ChattingEvent(), this); @@ -112,6 +115,8 @@ public class Core extends JavaPlugin{ @Override public void onDisable() { TinyProtocol.instance.close(); + if(VERSION > 15) + crashDetector.stop(); errorHandler.unregister(); if(!standalone) { Statement.close(); diff --git a/SpigotCore_Main/src/de/steamwar/core/CrashDetector.java b/SpigotCore_Main/src/de/steamwar/core/CrashDetector.java new file mode 100644 index 0000000..f62070a --- /dev/null +++ b/SpigotCore_Main/src/de/steamwar/core/CrashDetector.java @@ -0,0 +1,64 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2022 SteamWar.de-Serverteam + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package de.steamwar.core; + +import de.steamwar.sql.SWException; +import org.bukkit.Bukkit; + +import java.util.Arrays; +import java.util.concurrent.atomic.AtomicLong; +import java.util.stream.Collectors; + +public class CrashDetector { + + private static final long TIMEOUT = 20000; + private final AtomicLong lastTick = new AtomicLong(Long.MAX_VALUE); + private final Thread mainThread = Thread.currentThread(); + private final Thread watchdog; + + private boolean run = true; + + public CrashDetector () { + Bukkit.getScheduler().runTaskTimer(Core.getInstance(), () -> lastTick.set(System.currentTimeMillis()), 0, 1); + watchdog = new Thread(this::run, "SteamWar Watchdog"); + watchdog.setDaemon(true); + watchdog.start(); + } + + public void stop() { + run = false; + watchdog.interrupt(); + } + + private void run() { + while (run) { + long curTime = System.currentTimeMillis(); + if(curTime + TIMEOUT > lastTick.get()) { + SWException.log(Bukkit.getServer().getVersion() + " server hung for " + (curTime - lastTick.get()) + "ms, ", Arrays.stream(mainThread.getStackTrace()).map(StackTraceElement::toString).collect(Collectors.joining("\n"))); + lastTick.set(curTime); + } + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + } + } +}