package org.spigotmc; import java.io.File; import net.minecraft.server.EntityPlayer; import org.bukkit.command.Command; import org.bukkit.command.CommandSender; import org.torch.server.TorchServer; import com.google.common.collect.ImmutableList; public class RestartCommand extends Command { public RestartCommand(String name) { super(name); this.description = "Restarts the server"; this.usageMessage = "/restart"; this.setPermission("bukkit.command.restart"); } @Override public boolean execute(CommandSender sender, String currentAlias, String[] args) { if (testPermission(sender)) { TorchServer.getServer().processQueue.add(() -> restart()); } return true; } public static void restart() { restart(new File(SpigotConfig.restartScript)); } @SuppressWarnings("deprecation") public static void restart(final File script) { AsyncCatcher.enabled = false; // Disable async catcher incase it interferes with us try { if (script.isFile()) { System.out.println("Attempting to restart with " + SpigotConfig.restartScript); // Disable Watchdog WatchdogThread.doStop(); shutdownServer(); // Paper - Moved to function that will handle sync and async // This will be done AFTER the server has completely halted Thread shutdownHook = new Thread(() -> { try { String os = System.getProperty("os.name").toLowerCase(java.util.Locale.ENGLISH); if (os.contains("win")) { Runtime.getRuntime().exec("cmd /c start " + script.getPath()); } else { Runtime.getRuntime().exec(new String[] { "sh", script.getPath() }); } } catch (Exception e) { e.printStackTrace(); } }); shutdownHook.setDaemon(true); Runtime.getRuntime().addShutdownHook(shutdownHook); } else { System.out.println("Startup script '" + SpigotConfig.restartScript + "' does not exist! Stopping server."); // Actually shutdown try { TorchServer.getServer().stopServer(); } catch (Throwable t) { ; } } TorchServer.getServer().systemExitNow(); } catch (Exception ex) { ex.printStackTrace(); } } // Paper start - sync copied from above with minor changes, async added @SuppressWarnings("deprecation") private static void shutdownServer() { if (TorchServer.getServer().isMainThread()) { // Kick all players for (EntityPlayer player : ImmutableList.copyOf(TorchServer.getServer().getPlayerList().players)) { player.playerConnection.disconnect(SpigotConfig.restartMessage); } // Give the socket a chance to send the packets try { Thread.sleep(100); } catch (InterruptedException ex) { ; } closeSocket(); // Actually shutdown try { TorchServer.getServer().stopServer(); } catch (Throwable t) { ; } } else { closeSocket(); TorchServer.getServer().getServerThread().stop(); } } // Paper - Split from moved code private static void closeSocket() { // Close the socket so we can rebind with the new process TorchServer.getServer().getServerConnection().b(); // Give time for it to kick in try { Thread.sleep(100); } catch (InterruptedException ex) { ; } } // Paper end }