eclipse-vertx / vert.x

Vert.x is a tool-kit for building reactive applications on the JVM
http://vertx.io
Other
14.31k stars 2.08k forks source link

JVM stops right after deploying virtual verticle #5052

Open tsegismont opened 10 months ago

tsegismont commented 10 months ago

Consider this application:

public class MainVerticle extends AbstractVerticle {

  public static void main(String[] args) {
    Vertx vertx = Vertx.vertx();
    DeploymentOptions deploymentOptions = new DeploymentOptions()
      .setThreadingModel(ThreadingModel.VIRTUAL_THREAD);
    vertx.deployVerticle(new MainVerticle(), deploymentOptions)
      .onComplete(ar -> {
        if (ar.succeeded()) {
          System.out.println("Done");
        } else {
          ar.cause().printStackTrace();
        }
      });
  }

  @Override
  public void start(Promise<Void> startPromise) {
    vertx.createHttpServer().requestHandler(req -> {
      req.response()
        .putHeader("content-type", "text/plain")
        .end("Hello from Vert.x!");
    }).listen(8888, http -> {
      if (http.succeeded()) {
        startPromise.complete();
        System.out.println("HTTP server started on port 8888");
      } else {
        startPromise.fail(http.cause());
      }
    });
  }
}

The JVM stops before the server is bound. It does not happen if the verticle is deployed using the event loop or the worker threading model.

tsegismont commented 10 months ago

Quick analysis: when the virtual thread model is used, no event loop is created before the http server is started. Vert.x threads are non-daemon by default, and they prevent the JVM from shutting down.

In the sample before, the application reaches the end of the main method before the virtual thread triggers the creation of the http server.

That is why the JVM shut downs early.

tsegismont commented 10 months ago

cc @vietj

Many applications rely on the fact that the JVM will stay alive even after the main thread reaches the end of the method.

vietj commented 10 months ago

yeah I found this issue too a while ago, I don't know yet what is the best way to address it.

I believe that applications should not rely on vertx though

tsegismont commented 10 months ago

I just found that this (funny?) behavior:

vertx.deployVerticle(new MainVerticle(), deploymentOptions)

to:

vertx.deployVerticle(MainVerticle.class.getName(), deploymentOptions)

Then the JVM doesn't stop because Vert.x starts an event loop

I believe that applications should not rely on vertx though

I understand. On the other hand, we have so many examples which look like the example in the description.

tsegismont commented 10 months ago

Perhaps we can find the difference between deploying a verticle with a class name or with a class or an instance, and make sure it always works like deploying using a class name.

vietj commented 10 months ago

I believe we should start to provide different examples when the code is started from a non vertx thread, e.g.

vertx.deployVerticle(...).await();

would make sense to me

However await() currently is only supported on worker threads, but it would make sense to support it from a non vertx event-loop thread.