JDK-8146730 : LockSupport.parkUntil waits too long in case hibernation happened between invocation and deadline
  • Type: Bug
  • Component: hotspot
  • Sub-Component: runtime
  • Affected Version: 8u66,9
  • Priority: P4
  • Status: Open
  • Resolution: Unresolved
  • OS: windows_8
  • CPU: x86_64
  • Submitted: 2016-01-09
  • Updated: 2021-08-03
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
Other
tbdUnresolved
Related Reports
Relates :  
Relates :  
Description
The description of LockSupport.parkUntil clearly says that the provided deadline is an absolute instant encoded as milliseconds since the Epoch.

<quote>
@param deadline the absolute time, in milliseconds from the Epoch, to wait until
</quote>

Unfortunately either this description is simply wrong, or the implementation has a bug, because it is pretty simple to prove that the command will fail in some cases, for example when a phase of hibernation happened between invocation of the command and the provided deadline.

Steps to reproduce:
* Use JDK 8u66 on Win 8.1 (64 Bit). [Mac will provide different behaviour!]
* Start the program below.
* Instantly close the laptop lid to begin hibernation.
* Wait for 30 seconds.
* Open the laptop lid to cancel hibernation.
* Wait until the program prints the test result.

	static final void demonstrateSchedulerSleepover() {
		final long requestedDelay = 60L;
		final long startTime = System.nanoTime();
		LockSupport.parkUntil(Instant.now().plus(1L, ChronoUnit.MINUTES).toEpochMilli());
		System.out.printf("Requested Delay: %ds / Actual delay: %ds%n", requestedDelay, (System.nanoTime() - startTime) / 1000000000L, requestedDelay,
				TimeUnit.SECONDS);
	}

Expected result:
* Exactly 60 seconds after starting the program it should print "Requested Delay: 60s / Actual delay: 60s".

Actual result:
* About 90 seconds after starting the program it does print "Requested Delay: 60s / Actual delay: 90s".

Conclusion:
* Either the software works as designed, then the JavaDocs are simply wrong as parkUntil will _not_ fire at the given instant but much later in case of intermediate hibernation.
* Or the software is simply buggy, possibly because it uses a Windows API that has changed its implication since the invention of this Java API, or possibly because it uses the wrong Windows API.

Impact:
* There might be application software that heavily relies on the fact that this API works correctly in both cases, with *and* without intermediate hibernation. "Correctly" here means that the software MUST fire at that absolute instant, unless that instant lies *within* the hibernation phase (in the latter case, an instant firing has to happen at the end of the hibernation phase). Such software will clearly fail due to the random length of the hibernation phase. Depending on the use case, this might be a severe problem for such kind of applications. Such software typically is  e. g. production control software (ERP), business management, frequent mail inbound checks, etc.
Comments
It has been deferred. It is a low priority, and complex, issue no one is actively assigned to it.
04-04-2019

Any news on this topic?
17-04-2017

There may be a solution for windows. However consistency across all platforms is a much bigger issue - and I have no way to test suspension behaviour other than on Windows. All the *NIX platforms, other than Linux, use the default pthread_cond_init settings and so the timeout (which is always specified as an absolute time for pthread_condtimedwait) is always based on the CLOCK_REALTIME clock - which is wall-time. On Linux we use CLOCK_MONOTONIC for relative timeouts (still specified as absolute times) and CLOCK_REALTIME for absolute timeouts - this was to avoid the problem of relative timeouts being affected by changes to the system clock (due to ntp etc not suspension!). I have no idea how each OS handles the updates to CLOCK_REALTIME when suspension has occurred, or how that may be communicated through to pthread_condtimedwait. Note that because the *NIX platforms use the same clock for both relative and absolute timeouts then the behaviour with regard to suspension can not possibly be correct for both cases! So there would be a large amount of work to be done to have all platforms act consistently here.
09-02-2017

I can't help with Windows but in general I support Markus' idea, especially if we can achieve consistency on all JDK platforms.
12-01-2016

As I have a "failing system" (Win 8.1 64 Bit) here and as I have a rather solid understanding of Win32 API, I can offer to run some tests in Visual C++ to replace "looks like a solution" by "definitively is the solution" if you like. :-)
11-01-2016

Moving to hotspot->runtime.
10-01-2016

As discussed in JDK-8146527 these API's were never designed to work across PC suspension/hibernation. The absolute time API's do suffer on Windows because Windows does not support absolute times in any of its timed-blocking synchronization APIs. Hence on Windows the absolute time is converted to a relative time in a call to waitForMultipleObjects. If the real absolute time changes suddenly (from the perspective of the OS/VM) either because of suspension or because the time was changed directly, then this will not be noticed and the call will not timeout until the relative time has been seen to elapse. On POSIX based OS we now use a condvar associated with the real-time clock for absolute timed waits, so if the OS updates the condvar in relation to the sudden time change, then the Java API's will behave as expected. To resolve this on Windows it looks like a "waittable timer": https://msdn.microsoft.com/en-us/library/windows/desktop/ms687012%28v=vs.85%29.aspx can be used to provide the absolute timeout. The documentation indicates that the timer will be signalled if the absolute time changes externally - though it does not mention PC suspension explicitly.
10-01-2016