Repository: quarkusio/quarkus
Issue: Dev mode first hot reload request is 'ignored' if there is no active REST endpoint on the service under Ubuntu

### Describe the bug

In the `intellij` terminal the first `s` triggers a manual restart when the Quarkus service has an active REST endpoint.
But if it doesn't have one, then the first `s` is ignored and restart only occurs on sending the second one as well.

### Expected behavior

Restart on the first request.

### Actual behavior

Restarts only on the second request even if minutes pass between the two.

### How to Reproduce?

A reproducer can be found at: 
https://github.com/tlvlp/quarkus-hot-reload-test (Note: it's only an empty, freshly generated project.)

1. Launch the service
2. Wait for the build and dev mode to load and for the service to start.
3. Make any changes to the code.
4. Select intellij's terminal
5. Press 's' and 'enter
6. Nothing happens
7. Repeat step 5.
8. The service hot-reload is triggered.

### Output of `uname -a` or `ver`

Linux tux 5.11.0-34-generic #36~20.04.1-Ubuntu SMP Fri Aug 27 08:06:32 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux

### Output of `java -version`

openjdk version "17" 2021-09-14 OpenJDK Runtime Environment (build 17+35-2724) OpenJDK 64-Bit Server VM (build 17+35-2724, mixed mode, sharing)

### GraalVM version (if different from Java)

n/a

### Quarkus version or git rev

2.3.1.Final

### Build tool (ie. output of `mvnw --version` or `gradlew --version`)

Maven 3.8.1

### Additional information

Related to #20809 where the affected code segment is also mentioned.



```
Linux 5.11.0-34-generic
Current Desktop: ubuntu:GNOME
IntelliJ IDEA 2021.2.3 (Ultimate Edition)
Build #IU-212.5457.46, built on October 12, 2021
Runtime version: 11.0.12+7-b1504.40 amd64
VM: OpenJDK 64-Bit Server VM by JetBrains s.r.o.

com.redhat.devtools.intellij.quarkus (1.8.0.176)
```

Changed files:
devtools/maven/src/main/java/io/quarkus/maven/DevMojo.java

diff --git a/devtools/maven/src/main/java/io/quarkus/maven/DevMojo.java b/devtools/maven/src/main/java/io/quarkus/maven/DevMojo.java
index 2381a90dc31..f40fdeb9abb 100644
--- a/devtools/maven/src/main/java/io/quarkus/maven/DevMojo.java
+++ b/devtools/maven/src/main/java/io/quarkus/maven/DevMojo.java
@@ -12,6 +12,7 @@
 import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.nio.file.Paths;
@@ -27,14 +28,13 @@
 import java.util.Optional;
 import java.util.Properties;
 import java.util.Set;
-import java.util.function.Consumer;
 import java.util.stream.Collectors;
 import java.util.zip.ZipEntry;
 import java.util.zip.ZipFile;
 
-import org.aesh.readline.tty.terminal.TerminalConnection;
+import org.aesh.readline.terminal.impl.ExecPty;
+import org.aesh.readline.terminal.impl.Pty;
 import org.aesh.terminal.Attributes;
-import org.aesh.terminal.Connection;
 import org.aesh.terminal.utils.ANSI;
 import org.apache.maven.artifact.Artifact;
 import org.apache.maven.execution.MavenSession;
@@ -337,7 +337,7 @@ public class DevMojo extends AbstractMojo {
     private Attributes attributes;
     private int windowsAttributes;
     private boolean windowsAttributesSet;
-    private Connection connection;
+    private Pty pty;
     private boolean windowsColorSupport;
 
     @Override
@@ -438,21 +438,15 @@ private void saveTerminalState() {
                 }
             }
         } catch (Throwable t) {
+            //this only works with a proper PTY based terminal
+            //Aesh creates an input pump thread, that will steal
+            //input from the dev mode process
             try {
-                //this does not work on windows
-                //jansi creates an input pump thread, that will steal
-                //input from the dev mode process
-                new TerminalConnection(new Consumer<Connection>() {
-                    @Override
-                    public void accept(Connection connection) {
-                        attributes = connection.getAttributes();
-                        DevMojo.this.connection = connection;
-                    }
-                });
-            } catch (IOException e) {
-                getLog().error(
-                        "Failed to setup console restore, console may be left in an inconsistent state if the process is killed",
-                        e);
+                Pty pty = ExecPty.current();
+                attributes = pty.getAttr();
+                DevMojo.this.pty = pty;
+            } catch (Exception e) {
+                getLog().debug("Failed to get a local tty", e);
             }
         }
     }
@@ -461,16 +455,21 @@ private void restoreTerminalState() {
         if (windowsAttributesSet) {
             WindowsSupport.setConsoleMode(windowsAttributes);
         } else {
-            if (attributes == null || connection == null) {
+            if (attributes == null || pty == null) {
                 return;
             }
-            connection.setAttributes(attributes);
-            int height = connection.size().getHeight();
-            connection.write(ANSI.MAIN_BUFFER);
-            connection.write(ANSI.CURSOR_SHOW);
-            connection.write("\\u001B[0m");
-            connection.write("\\033[" + height + ";0H");
-            connection.close();
+            Pty finalPty = pty;
+            try (finalPty) {
+                finalPty.setAttr(attributes);
+                int height = finalPty.getSize().getHeight();
+                String sb = ANSI.MAIN_BUFFER +
+                        ANSI.CURSOR_SHOW +
+                        "\\u001B[0m" +
+                        "\\033[" + height + ";0H";
+                finalPty.getSlaveOutput().write(sb.getBytes(StandardCharsets.UTF_8));
+            } catch (IOException e) {
+                getLog().error("Error restoring console state", e);
+            }
         }
     }