Uploaded image for project: 'Minecraft: Java Edition'
  1. Minecraft: Java Edition
  2. MC-228953

Ctrl + C does not completely stop dedicated server with GUI

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Unresolved
    • None
    • 1.17, 1.17.1 Pre-release 1, 22w18a, 1.19.1 Pre-release 2
    • None
    • Plausible
    • Dedicated Server

      The bug

      OS: Windows 10

      When starting the dedicated server with GUI from command line (i.e. without --nogui command line argument) and then using Ctrl + C to stop it, it properly disconnects all players but then gets stuck.

      Reproduction steps

      1. Download JDK 16 (or newer, depending on the latest Minecraft requirements)
      2. Download the dedicated server from https://www.minecraft.net/en-us/download/server
      3. Start the dedicated server from command line
        java -jar ./server.jar
        
      4. Once the server has finished starting, press Ctrl + C in the command prompt / terminal (not the Minecraft server GUI!)
        In case players were connected you will see that they are properly disconnected
        Server shutdown gets stuck, the process does not exit

      Code analysis

      Minecraft 1.17, Mojang names

      A thread dump shows that it gets stuck trying to dispose the GUI:

      "Server thread" #29 prio=5 os_prio=0 cpu=4109.38ms elapsed=34.06s tid=0x0000017a411b17b0 nid=0x1478 in Object.wait()  [0x000000719880e000]
         java.lang.Thread.State: WAITING (on object monitor)
              at java.lang.Object.wait(java.base@16/Native Method)
              - waiting on <no object reference available>
              at java.lang.Object.wait(java.base@16/Object.java:320)
              at java.awt.EventQueue.invokeAndWait(java.desktop@16/EventQueue.java:1362)
              - locked <0x00000000ae000878> (a java.awt.EventQueue$1AWTInvocationLock)
              at java.awt.Window.doDispose(java.desktop@16/Window.java:1228)
              at java.awt.Window.dispose(java.desktop@16/Window.java:1165)
              at aay$$Lambda$4009/0x000000080138e780.run(Unknown Source)
              at aay$$Lambda$4571/0x00000008015dcac8.accept(Unknown Source)
              at java.util.ArrayList.forEach(java.base@16/ArrayList.java:1511)
              at aay.f(SourceFile:157)
              at aay.b(SourceFile:152)
              at aas.f(SourceFile:320)
              at net.minecraft.server.MinecraftServer.x(SourceFile:733)
              at net.minecraft.server.MinecraftServer.a(SourceFile:274)
              at net.minecraft.server.MinecraftServer$$Lambda$3902/0x0000000801381d08.run(Unknown Source)
              at java.lang.Thread.run(java.base@16/Thread.java:831)
      

      The reason for this might be that net.minecraft.server.gui.MinecraftServerGui.runFinalizers() is not run from the AWT event dispatch thread. close() which calls it should probably wrap the call to it inside javax.swing.SwingUtilities.invokeAndWait(Runnable).

      The same also applies to net.minecraft.server.gui.MinecraftServerGui.showFrameFor(DedicatedServer) which should create the GUI from the AWT event dispatch thread.
      And for what it's worth net.minecraft.server.gui.StatsComponent should probably not access any MinecraftServer fields without synchronization either since there is no guarantee that it sees up to date values (since its tick() method runs on the AWT event dispatch thread).
      And net.minecraft.server.gui.PlayerListComponent.tick() should call setListData from the AWT event dispatch thread (use invokeLater here).

      The call to createCommandSourceStack() from the command text field action listener might not be thread-safe either.

            Unassigned Unassigned
            marcono1234 [Mod] Marcono1234
            Votes:
            2 Vote for this issue
            Watchers:
            3 Start watching this issue

              Created:
              Updated:
              CHK: