Error stacktrace lost

152 views
Skip to first unread message

Adrian Filip

unread,
Aug 23, 2016, 6:35:40 AM8/23/16
to vert.x
Hi,

In the code below I am intentionally causing an error by calling future complete twice.



fun main(args: Array<String>) {
val vertx = Vertx.vertx(VertxOptions().setWorkerPoolSize(40))

vertx.executeBlocking(
{ future: Future<String> ->
run {
try {

val result = BlockingCodeCaller.blockingMethod()
future.complete(result)
future.complete(result)
} catch(e: Throwable){
future.fail(e)
}


}
},
{ result ->
println("It does not reach this!")
when {
result.succeeded() -> println("succeeded")
result.failed() -> println("failed")
}
}
)
}





 All I see as error is:
Aug 23, 2016 1:16:38 PM io.vertx.core.impl.OrderedExecutorFactory
SEVERE: Caught unexpected Throwable
java.lang.IllegalStateException: Result is already complete: succeeded
at io.vertx.core.impl.FutureImpl.checkComplete(FutureImpl.java:164)
at io.vertx.core.impl.FutureImpl.fail(FutureImpl.java:145)
at io.vertx.core.impl.ContextImpl.lambda$executeBlocking$2(ContextImpl.java:309)
at io.vertx.core.impl.OrderedExecutorFactory$OrderedExecutor.lambda$new$0(OrderedExecutorFactory.java:94)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)

My question would be:
1. Why is the point of failure not mentioned in the stacktrace?
2. Why is this not going via the reply handler?

Best regards,
Adrian

Alexander Lehmann

unread,
Aug 23, 2016, 8:01:16 AM8/23/16
to vert.x
The contract of Future is that it is either complete or failed, but not both, so I assume a 2nd call to either is a failure but an exception of the Future.xxx() method

The point of failure is your future.fail call, which fails since the future is already complete, so it doesn't use the exception passed to the fail method.

I think the same would work if you used a new Future for your result

Alexander Lehmann

unread,
Aug 23, 2016, 8:06:12 AM8/23/16
to vert.x
sorry, the first line should read:

... so I assume a 2nd call to either is not a failure (of the Future) but an exception of the Future.xxx() method

Adrian Filip

unread,
Aug 23, 2016, 9:38:40 AM8/23/16
to ve...@googlegroups.com
You are right about the reason why it failed to get it in the reply handler. It was indeed because future.fail was also a point of failure.

The first question still remains though.
How can I make Vert.x also point me to the line where a failure occured?


Alexander Lehmann

unread,
Aug 23, 2016, 3:40:28 PM8/23/16
to vert.x
You have to use another Future to pass the complete result and use the Future provided by executeBlocking to pass the exception (which means you are dropping your result in this case)

I think it would be better to log the exception in the case where the complete was already called on the Future, the exception will not likely happen in any case except when forcing it.

Any real exception in your code will be passed to the Future since it happens before the complete is called:

try {
  val result
= BlockingCodeCaller.blockingMethod()

 
...
 
throw new Exception()
 
...
  future
.complete(result)
 
} catch(e: Throwable){
 
if (future.isCompleted()) {
  log
.error("Exception on completed Future", e)
 
} else {
   future
.fail(e)
}







will pass the exception to the executeBlocking

Adrian Filip

unread,
Aug 23, 2016, 4:08:35 PM8/23/16
to vert.x
This answers my questions.
Thanks Alexander! 
Reply all
Reply to author
Forward
0 new messages