Triggers fired milliseconds too early #83

herrmic opened this Issue Dec 11, 2012 · 4 comments


None yet
3 participants

herrmic commented Dec 11, 2012

I experienced triggers being fired 1 millisecond ahead of schedule.
In my application I create among others simple triggers that should fire once at specified time. I use TriggerBuilder.StartAt method to set the time. Method's documentation says:

the Trigger will NOT fire before this time, regardless of the Trigger's schedule

However, in the log files I sometimes see that task scheduled for 2012-11-28 07:12:24 runs at 2012-11-28 07:12:23,999. This clearly breaks the method's contract. And it breaks the application.
It is very hard to reproduce, it occurs only on one machine and not all the time.

I looked around Quartz code and I think that problem is caused by the following line in the QuartzSchedulerThread class:

while (timeUntilTrigger > TimeSpan.FromMilliseconds(2))

It seems that this implementation is fine with firing triggers 1 or 2 milliseconds before schedule. This is however not what the documentation/specification says.


lahma commented Dec 16, 2012

I'd say this is by design. It's probably impossible to ever get millisecond precision of fire time with all locking and extra checks that need to be done. If you are OK with running possible a bit after the schedule but not before, should you schedule you runs a couple milliseconds later?

herrmic commented Dec 23, 2012

I think that this issue is relatively easy to fix. QuartzSchedulerThread class has a loop that is exited when it's time to fire a trigger. Problem is that the code allows exiting the loop up to 2 milliseconds before firing time (the code is very explicit about this, it uses TimeSpan.FromMilliseconds(2)). I think that hidden assumption here is that it will take at least 2 milliseconds before job code is actually reached. However, on fast computers, job code is executed quicker.

The easiest way to fix the bug is to remove that additional loop exit condition and don't exit the loop ahead of schedule. More complex one is to wait before actually calling the job (spin-wait perhaps, if it's sensible to spin for 1 or 2 milliseconds).
I know that millisecond precision is not possible. But while it's perfectly acceptable to have code launched few milliseconds after the schedule (it is never possible to predict what will slow us down anyway), being run too early can be disastrous.

I can fix this myself and send you a patch if that's OK.

It is possible to schedule my jobs few milliseconds later. However, the exact value of "few" depends on implementation detail which is not public or guaranteed to remain unchanged. It would be workaround for a bug which I think is easily solvable.

I have to say its NOT ok for it to fire to early this can have devastating effects, in my case it was ok to be to late so i just added a few milliseconds for good measure but this has to be fixed..

By design i would say its ok to be to late but its not ok to be to early.

How upset would you be if you arrived at the train station only to realize that the train left early?

lahma added this to the 2.2.5 milestone Nov 2, 2014

lahma closed this in b87f209 Nov 2, 2014


lahma commented Nov 2, 2014

Even though I'm fine with the train leaving two milliseconds ahead of time (kidding here), I've now pushed a change to check against TimeSpan zero instead of the 2 millisecond window.

@lahma lahma modified the milestone: 2.3, 2.2.5 Nov 8, 2014

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment