diff options
author | Viktor Klang <viktor.klang@gmail.com> | 2014-12-20 19:51:43 +0100 |
---|---|---|
committer | Jason Zaugg <jzaugg@gmail.com> | 2015-02-04 14:04:05 +1000 |
commit | bf20737faa2da5b45ad1ef5e6a43dff307c99788 (patch) | |
tree | 235f68bfa6b187f2e7d9ad12a84610bdec41c8f4 /src | |
parent | ad0ddd4603e6ec134460491333444d505d376883 (diff) | |
download | scala-bf20737faa2da5b45ad1ef5e6a43dff307c99788.tar.gz scala-bf20737faa2da5b45ad1ef5e6a43dff307c99788.tar.bz2 scala-bf20737faa2da5b45ad1ef5e6a43dff307c99788.zip |
SI-8689 Avoid internal error in Promise after sequence of completions
Calling `completeWith` when the `DefaultPromise` is already completed,
leads to callbacks not being properly executed.
This happened because `Future.InternalCallbackExecutor` extends
`BatchingExecutor`[1] which assumes `unbatchedExecute` to be async,
when in this case it is sync, and if there is an exception thrown
by executing the batch, it creates a new batch with the remaining
items from the current batch and submits that to `unbatchedExecute`
and then rethrows, but if you have a sync `unbatchedExecute`, it will
fail since it is not reentrant, as witnessed by the failed `require`
as reported in this issue.
This commit avoids problem by delegating `completeWith` to
`tryComplete`, which has the effect of using `onComplete` +
`tryComplete` i.s.o. `complete`, which means that when it fails
(because of a benign race condition between completers) it won't
throw an exception.
It has been tested by the minimized reproducer.
[1] Actually, in the 2.10.x branch where this patch is starting out,
"The BatchingExecutor trait had to be inlined into
InternalCallbackExecutor for binary compatibility.". This comment
will be more literally correct in the context of 2.11.x and beyond
Diffstat (limited to 'src')
-rw-r--r-- | src/library/scala/concurrent/Promise.scala | 7 |
1 files changed, 2 insertions, 5 deletions
diff --git a/src/library/scala/concurrent/Promise.scala b/src/library/scala/concurrent/Promise.scala index 8355a73a1f..02253d4bd9 100644 --- a/src/library/scala/concurrent/Promise.scala +++ b/src/library/scala/concurrent/Promise.scala @@ -66,11 +66,8 @@ trait Promise[T] { * * @return This promise */ - final def completeWith(other: Future[T]): this.type = { - other onComplete { this complete _ } - this - } - + final def completeWith(other: Future[T]): this.type = tryCompleteWith(other) + /** Attempts to complete this promise with the specified future, once that future is completed. * * @return This promise |