Repository: vert-x3/vertx-web
Issue: SockJSHandlerTest intermittent failures in CI

### Questions

There is an intermittent failures about `SockJSHandlerTest` in CI

### Version

`master` branch

### Context

### Exceptions found

```java
Starting test: SockJSHandlerTest#testCombineBinaryContinuationFramesRawWebSocket 
Unhandled exception 
java.lang.IllegalStateException: assert or failure occurred after test has completed
	at io.vertx.test.core.AsyncTestBase.handleThrowable(AsyncTestBase.java:183)
	at io.vertx.test.core.AsyncTestBase.fail(AsyncTestBase.java:422)
	at io.vertx.core.impl.AbstractContext.dispatch(AbstractContext.java:96)
	at io.vertx.core.http.impl.WebSocketImplBase.handleClosed(WebSocketImplBase.java:694)
	at io.vertx.core.http.impl.Http1xServerConnection.lambda$handleClosed$6(Http1xServerConnection.java:458)
	at io.vertx.core.impl.EventLoopContext.execute(EventLoopContext.java:73)
	at io.vertx.core.impl.DuplicatedContext.execute(DuplicatedContext.java:184)
	at io.vertx.core.impl.AbstractContext.execute(AbstractContext.java:54)
	at io.vertx.core.http.impl.Http1xServerConnection.handleClosed(Http1xServerConnection.java:458)
	at io.vertx.core.net.impl.VertxHandler.channelInactive(VertxHandler.java:136)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:262)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:248)
	at io.netty.channel.AbstractChannelHandlerContext.fireChannelInactive(AbstractChannelHandlerContext.java:241)
	at io.netty.handler.codec.ByteToMessageDecoder.channelInputClosed(ByteToMessageDecoder.java:389)
	at io.netty.handler.codec.ByteToMessageDecoder.channelInactive(ByteToMessageDecoder.java:354)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:262)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:248)
	at io.netty.channel.AbstractChannelHandlerContext.fireChannelInactive(AbstractChannelHandlerContext.java:241)
	at io.netty.channel.DefaultChannelPipeline$HeadContext.channelInactive(DefaultChannelPipeline.java:1405)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:262)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:248)
	at io.netty.channel.DefaultChannelPipeline.fireChannelInactive(DefaultChannelPipeline.java:901)
	at io.netty.channel.AbstractChannel$AbstractUnsafe$8.run(AbstractChannel.java:818)
	at io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java:164)
	at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:472)
	at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:497)
	at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:989)
	at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
	at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
	at java.lang.Thread.run(Thread.java:748)
```

### Do you have a reproducer?

https://travis-ci.org/github/vert-x3/vertx-web/jobs/731209417 as reference

### Extra

* Looks like it happens in `OpenJDK8` mostly.


Changed files:
vertx-web/src/test/java/io/vertx/ext/web/WebTestBase.java
vertx-web/src/main/java/io/vertx/ext/web/handler/sockjs/impl/SockJSSession.java
vertx-template-engines/vertx-web-templ-pebble/src/main/java/io/vertx/ext/web/templ/pebble/PebbleTemplateEngine.java

diff --git a/vertx-template-engines/vertx-web-templ-pebble/src/main/java/io/vertx/ext/web/templ/pebble/PebbleTemplateEngine.java b/vertx-template-engines/vertx-web-templ-pebble/src/main/java/io/vertx/ext/web/templ/pebble/PebbleTemplateEngine.java
index db07598b9..7c3e7e86c 100644
--- a/vertx-template-engines/vertx-web-templ-pebble/src/main/java/io/vertx/ext/web/templ/pebble/PebbleTemplateEngine.java
+++ b/vertx-template-engines/vertx-web-templ-pebble/src/main/java/io/vertx/ext/web/templ/pebble/PebbleTemplateEngine.java
@@ -62,7 +62,7 @@ public interface PebbleTemplateEngine extends TemplateEngine {
    */
   @GenIgnore
   static PebbleTemplateEngine create(Vertx vertx, PebbleEngine engine) {
-    return new PebbleTemplateEngineImpl(vertx, DEFAULT_TEMPLATE_EXTENSION, engine);
+    return create(vertx, DEFAULT_TEMPLATE_EXTENSION, engine);
   }
 
   /**
diff --git a/vertx-web/src/main/java/io/vertx/ext/web/handler/sockjs/impl/SockJSSession.java b/vertx-web/src/main/java/io/vertx/ext/web/handler/sockjs/impl/SockJSSession.java
index 9f7eda5ba..7e13a9ca1 100644
--- a/vertx-web/src/main/java/io/vertx/ext/web/handler/sockjs/impl/SockJSSession.java
+++ b/vertx-web/src/main/java/io/vertx/ext/web/handler/sockjs/impl/SockJSSession.java
@@ -395,12 +395,16 @@ class SockJSSession extends SockJSSocketBase implements Shareable {
     }
   }
 
-  synchronized void handleException(Throwable t) {
-    if (exceptionHandler != null) {
+  void handleException(Throwable t) {
+    Handler<Throwable> eh;
+    synchronized (this) {
+      eh = exceptionHandler;
+    }
+    if (eh != null) {
       if (context == Vertx.currentContext()) {
-        exceptionHandler.handle(t);
+        eh.handle(t);
       } else {
-        context.runOnContext(v -> exceptionHandler.handle(t));
+        context.runOnContext(v -> handleException(t));
       }
     } else {
       log.error("Unhandled exception", t);
diff --git a/vertx-web/src/test/java/io/vertx/ext/web/WebTestBase.java b/vertx-web/src/test/java/io/vertx/ext/web/WebTestBase.java
index 5400af059..7e5db09f6 100644
--- a/vertx-web/src/test/java/io/vertx/ext/web/WebTestBase.java
+++ b/vertx-web/src/test/java/io/vertx/ext/web/WebTestBase.java
@@ -73,10 +73,12 @@ public class WebTestBase extends VertxTestBase {
   @Override
   public void tearDown() throws Exception {
     if (client != null) {
-      try {
-        client.close();
-      } catch (IllegalStateException e) {
-      }
+      CountDownLatch latch = new CountDownLatch(1);
+      client.close((asyncResult) -> {
+        assertTrue(asyncResult.succeeded());
+        latch.countDown();
+      });
+      awaitLatch(latch);
     }
     if (server != null) {
       CountDownLatch latch = new CountDownLatch(1);