public function forceShutdown()
{
if ($this->hasStopped) {
return;
}
try {
if (!$this->isRunning()) {
$this->sendUsage(SendUsageTask::TYPE_CLOSE);
}
$this->hasStopped = true;
$this->shutdown();
if ($this->rcon instanceof RCON) {
$this->rcon->stop();
}
if ($this->getProperty("network.upnp-forwarding", false) === true) {
$this->logger->info("[UPnP] Removing port forward...");
UPnP::RemovePortForward($this->getPort());
}
$this->getLogger()->debug("Disabling all plugins");
$this->pluginManager->disablePlugins();
foreach ($this->players as $player) {
$reason = $this->shutdownreason;
if (trim($reason) !== "") {
$player->close($player->getLeaveMessage(), $reason);
} else {
$player->close($player->getLeaveMessage(), $this->getProperty("settings.shutdown-message", "Server closed"));
}
}
$this->getLogger()->debug("Unloading all levels");
foreach ($this->getLevels() as $level) {
$this->unloadLevel($level, true);
}
$this->getLogger()->debug("Removing event handlers");
HandlerList::unregisterAll();
$this->getLogger()->debug("Stopping all tasks");
$this->scheduler->cancelAllTasks();
$this->scheduler->mainThreadHeartbeat(PHP_INT_MAX);
$this->getLogger()->debug("Saving properties");
$this->properties->save();
$this->getLogger()->debug("Closing console");
$this->console->shutdown();
$this->console->notify();
$this->getLogger()->debug("Stopping network interfaces");
foreach ($this->network->getInterfaces() as $interface) {
$interface->shutdown();
$this->network->unregisterInterface($interface);
}
$this->memoryManager->doObjectCleanup();
gc_collect_cycles();
} catch (\Throwable $e) {
$this->logger->logException($e);
$this->logger->emergency("Crashed while crashing, killing process");
@kill(getmypid());
}
}
public function dumpServerMemory($outputFolder, $maxNesting, $maxStringSize) { gc_disable(); if (!file_exists($outputFolder)) { mkdir($outputFolder, 0777, true); } $this->server->getLogger()->notice("[Dump] After the memory dump is done, the server might crash"); $obData = fopen($outputFolder . "/objects.js", "wb+"); $staticProperties = []; $data = []; $objects = []; $refCounts = []; $this->continueDump($this->server, $data, $objects, $refCounts, 0, $maxNesting, $maxStringSize); do { $continue = false; foreach ($objects as $hash => $object) { if (!is_object($object)) { continue; } $continue = true; $className = get_class($object); $objects[$hash] = true; $reflection = new \ReflectionObject($object); $info = ["information" => "{$hash}@{$className}", "properties" => []]; if ($reflection->getParentClass()) { $info["parent"] = $reflection->getParentClass()->getName(); } if (count($reflection->getInterfaceNames()) > 0) { $info["implements"] = implode(", ", $reflection->getInterfaceNames()); } foreach ($reflection->getProperties() as $property) { if ($property->isStatic()) { continue; } if (!$property->isPublic()) { $property->setAccessible(true); } $this->continueDump($property->getValue($object), $info["properties"][$property->getName()], $objects, $refCounts, 0, $maxNesting, $maxStringSize); } fwrite($obData, "{$hash}@{$className}: " . json_encode($info, JSON_UNESCAPED_SLASHES) . "\n"); if (!isset($objects["staticProperties"][$className])) { $staticProperties[$className] = []; foreach ($reflection->getProperties() as $property) { if (!$property->isStatic() or $property->getDeclaringClass()->getName() !== $className) { continue; } if (!$property->isPublic()) { $property->setAccessible(true); } $this->continueDump($property->getValue($object), $staticProperties[$className][$property->getName()], $objects, $refCounts, 0, $maxNesting, $maxStringSize); } } } echo "[Dump] Wrote " . count($objects) . " objects\n"; } while ($continue); file_put_contents($outputFolder . "/staticProperties.js", json_encode($staticProperties, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT)); file_put_contents($outputFolder . "/serverEntry.js", json_encode($data, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT)); file_put_contents($outputFolder . "/referenceCounts.js", json_encode($refCounts, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT)); echo "[Dump] Finished!\n"; gc_enable(); $this->server->forceShutdown(); }