JDK-7139684 : ScheduledExecutorService doesn't schedules correctly if sys time drifts back
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.util.concurrent
  • Affected Version: 6u29
  • Priority: P4
  • Status: Closed
  • Resolution: Duplicate
  • OS: linux_ubuntu
  • CPU: x86
  • Submitted: 2012-01-29
  • Updated: 2012-03-20
  • Resolved: 2012-01-29
Related Reports
Duplicate :  
Relates :  
Description
FULL PRODUCT VERSION :
java version "1.6.0_26"
Java(TM) SE Runtime Environment (build 1.6.0_26-b03)
Java HotSpot(TM) 64-Bit Server VM (build 20.1-b02, mixed mode)


ADDITIONAL OS VERSION INFORMATION :
Linux ykarachiwala 3.0.0-15-generic #26-Ubuntu SMP Fri Jan 20 17:23:00 UTC 2012 x86_64 x86_64 x86_64 GNU/Linux

A DESCRIPTION OF THE PROBLEM :
When using ScheduledExecutorService there is issue :
Tasks scheduled before system time change (through ntpd) are not executed on delay specified. Have no logs for same as nothing happens :(.

ScheduledExecutorService works fine on Windows. Problem is only on 64 bit Linux based system running 64 bit JVM. It works fine on 64 bit linux running 32 bit JVM...strange. Have not found any reference of same on any blogs either.

http://stackoverflow.com/questions/9044423/java-scheduler-which-is-completely-independent-of-system-time-changes

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Run following program and keep changing time:

package test;

import java.io.IOException;
import java.util.Date;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

/**
 * @author yogesh
 *
 */
public class TimerCheck  implements Runnable {

    ScheduledExecutorService worker;


    public TimerCheck(ScheduledExecutorService worker) {
        super();
        this.worker = worker;
        this.worker.schedule(this, 1, TimeUnit.SECONDS);
    }

    private static void update() {
        System.out.println("TimerCheck.update() "+new Date(System.currentTimeMillis()));
    }

    @Override
    public void run() {
            update();
            worker.schedule(this, 1, TimeUnit.SECONDS);
    }

    /**
     * @param args
     */
    public static void main(String[] args) {
        ScheduledExecutorService worker = Executors.newScheduledThreadPool(1);
        new TimerCheck(worker);
    }

}

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Task scheduled should run despite of time switch backward.
ACTUAL -
Task is stalled.

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
package test;

import java.io.IOException;
import java.util.Date;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

/**
 * @author yogesh
 *
 */
public class TimerCheck  implements Runnable {

    ScheduledExecutorService worker;


    public TimerCheck(ScheduledExecutorService worker) {
        super();
        this.worker = worker;
        this.worker.schedule(this, 1, TimeUnit.SECONDS);
    }

    private static void update() {
        System.out.println("TimerCheck.update() "+new Date(System.currentTimeMillis()));
    }

    @Override
    public void run() {
            update();
            worker.schedule(this, 1, TimeUnit.SECONDS);
    }

    /**
     * @param args
     */
    public static void main(String[] args) {
        ScheduledExecutorService worker = Executors.newScheduledThreadPool(1);
        new TimerCheck(worker);
    }

}
---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
Works well with 32 bit JVM

Comments
EVALUATION This is a the same issue reported under 6900441. The basic problem is that the underlying pthread_condtimedwait waits for an absolute time based on the time-of-day clock. Hence if the clock goes backwards it will wait longer. The fix is to switch to use of CLOCK_MONOTONIC with the condition variable so that it is immune to changes in the time-of-day clock. The difference in behaviour between 32-bit and 64-bit VMs is strange to say the least as there is no code difference in the VM. But as noted in 7139684 Linux does not in general handle changes to the system clock correctly with regards to the futex implementation that underlies pthread condition variables.
29-01-2012