Repository: quarkusio/quarkus
Issue: @PreDestroy method seems to not be invocked when ExecutorManager is being used.

In the following project test-executor project

https://github.com/wmedvede/test-executor-issue.git

I have the silly component below.

All right, when I execute my application in dev mode, with mvn clean compile quarkus:dev

In can see that the created MyRunnable is executing, etc, as expected.
When I stop the application with "CTRL+C" the application stops gracefully, i.e. the @PreDestroy method is executed, the MyRunnable instance is stopped etc.

BUT, when I execute same application with

java -jar target/test-executor-1.0.0-SNAPSHOT-runner.jar (or with the generated native image)

There's no way to stop the application, i.e., the "CTRL+C" seems to simply do nothing in that particular scenario, and the @PreDestroy isn't invoked.


note: The @Observes ShutdownEvent works in all cases

`
@ApplicationScoped
@Startup
public class MyService {

    class MyRunnable implements Runnable {

        private AtomicBoolean exit = new AtomicBoolean(false);

        public void exit() {
            exit.set(true);
        }

        @Override
        public void run() {
            while (!exit.get()) {
                try {
                    Thread.sleep(2000);
                    System.out.println("MyRunnable is working!");
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                    exit.set(true);
                }
            }
            System.out.println("MyRunnable has finished it work!");
        }
    }

    @Inject
    ManagedExecutor managedExecutor;

    MyRunnable myRunnableInstance;

    @PostConstruct
    void startService() {
        myRunnableInstance = new MyRunnable();
        managedExecutor.execute(myRunnableInstance);
    }

    /**
     * When we stop the application with CTRL+C this method is only invoked when
     * the application is started in dev mode. But not in native or if we execute the java runner.
     */
    @PreDestroy
    void destroyService() {
        System.out.println("Destroying the service!");
        if (myRunnableInstance != null) {
            System.out.println("Destroying the runnable!");
            myRunnableInstance.exit();
        }
    }


    /*
    This variant is always invocked
    void onShutDownEvent(@Observes ShutdownEvent ev) {
        System.out.println("SHUT DOWN EVENT is executed!!!!");
        if (myRunnableInstance != null) {
            System.out.println("Destroying the runnable!");
            myRunnableInstance.exit();
        }
    }
    */
}
`

Changed files:
core/runtime/src/main/java/io/quarkus/runtime/ExecutorRecorder.java
extensions/arc/runtime/src/main/java/io/quarkus/arc/runtime/context/ArcContextProvider.java

diff --git a/core/runtime/src/main/java/io/quarkus/runtime/ExecutorRecorder.java b/core/runtime/src/main/java/io/quarkus/runtime/ExecutorRecorder.java
index d5b0f1618c0..372b4a0adbc 100644
--- a/core/runtime/src/main/java/io/quarkus/runtime/ExecutorRecorder.java
+++ b/core/runtime/src/main/java/io/quarkus/runtime/ExecutorRecorder.java
@@ -54,7 +54,7 @@ public void run() {
             executor = devModeExecutor;
             Runtime.getRuntime().addShutdownHook(new Thread(shutdownTask, "Executor shutdown thread"));
         } else {
-            shutdownContext.addShutdownTask(shutdownTask);
+            shutdownContext.addLastShutdownTask(shutdownTask);
             executor = underlying;
         }
         if (threadPoolConfig.prefill) {
diff --git a/extensions/arc/runtime/src/main/java/io/quarkus/arc/runtime/context/ArcContextProvider.java b/extensions/arc/runtime/src/main/java/io/quarkus/arc/runtime/context/ArcContextProvider.java
index 5537feb0935..92941faaa61 100644
--- a/extensions/arc/runtime/src/main/java/io/quarkus/arc/runtime/context/ArcContextProvider.java
+++ b/extensions/arc/runtime/src/main/java/io/quarkus/arc/runtime/context/ArcContextProvider.java
@@ -66,12 +66,6 @@ public String getThreadContextType() {
         return ThreadContext.CDI;
     }
 
-    // see ThreadContextController#endContext()
-    private static void deactivateRequestContext() throws IllegalStateException {
-        // Only deactivate the context
-        Arc.container().requestContext().deactivate();
-    }
-
     private static final class ClearContextSnapshot implements ThreadContextSnapshot {
 
         @Override
@@ -92,7 +86,7 @@ public ThreadContextController begin() {
             } else {
                 // context not active, activate blank one, deactivate afterwards
                 requestContext.activate();
-                return ArcContextProvider::deactivateRequestContext;
+                return requestContext::deactivate;
             }
         }
     }
@@ -155,7 +149,7 @@ public ThreadContextController begin() {
             } else {
                 // context not active, activate and pass it new instance, deactivate afterwards
                 requestContext.activate(state);
-                return ArcContextProvider::deactivateRequestContext;
+                return requestContext::deactivate;
             }
         }