The XNIO threads created by Undertow are non-daemon threads so they keep the JVM alive. If a request is active when the JVM is exiting, the XNIO thread that is handling the request will keep the JVM alive. The fix isn't as simple as configuring XNIO to create daemon threads as this then results in the JVM exiting as soon as the main method exits as there are no non-daemon threads to keep it alive.

It looks like we need to do the same as we do for Tomcat and create a non-daemon thread that doesn't exit until the web server is stopped.

Comment From: wilkinsona

Non-daemons aren't the problem, or perhaps aren't all of the problem. Even with daemon worker threads, calling Undertow.stop() will still block indefinitely as there's no shutdown timeout configured. To align with the other embedded web servers, we don't want to wait at all by default.