Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[JENKINS-48309] - Prevent TimeoutException in AsyncFutureImpl in the case of spurious wakeups #240

22 changes: 19 additions & 3 deletions src/main/java/hudson/remoting/AsyncFutureImpl.java
Expand Up @@ -23,6 +23,8 @@
*/
package hudson.remoting;

import javax.annotation.CheckForNull;
import javax.annotation.Nonnegative;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
Expand Down Expand Up @@ -78,13 +80,27 @@ public synchronized V get() throws InterruptedException, ExecutionException {
return value;
}

public synchronized V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
if(!completed)
wait(unit.toMillis(timeout));
@CheckForNull
public synchronized V get(@Nonnegative long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
// The accuracy of wait(long) operation is milliseconds anyway, but ok.
long endWaitTime = System.nanoTime() + unit.toNanos(timeout);
while (!completed) {
long timeToWait = endWaitTime - System.nanoTime();
if (timeToWait < 0) {
break;
}

wait(timeToWait / 1000000, (int)(timeToWait % 1000000));
}

if(!completed)
throw new TimeoutException();
if(cancelled)
throw new CancellationException();

//TODO: we may be calling a complex get() implementation in the override, which may hang the code
// The only missing behavior is "problem!=null" branch, but probably we cannot just replace the code without
// an override issue risk.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Then perhaps move the get outside the synchronised

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will need to investigate the implementations first. get() outside synchronized may help for sure, but I would like to find real examples before touching this code.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ack

return get();
}

Expand Down