Calling 'new Date()' more than once in an init function is problematic

Bug #1864056 reported by Jason Boyer
6
This bug affects 1 person
Affects Status Importance Assigned to Milestone
Evergreen
Fix Released
High
Unassigned
3.3
Won't Fix
High
Unassigned
3.4
Fix Released
High
Unassigned

Bug Description

Evergreen 3.3.6 / 3.4.2 / master
Bug 1712644 is a great fix (I look forward to never again cleaning up a circ in December that was accidentally made due a year ago!) however, it allowed a race condition to surface that's been hiding in one or more Angular initializers, in this case circ/patron/checkout.js The way this presents itself is by the Out of Range error appearing immediately on loading the checkout screen.

Let's consider some code:
$scope.checkoutArgs = {
    noncat_type : 'barcode',
    due_date : new Date()
};

$scope.minDate = new Date();

Innocent enough, eh? Surely due_date and minDate are the same, they're called at the same time!
I've attached a little test file that just does this 10000 times in a row and tells you about every time the two times differ when comparing their whole second times. It's really rare not to get multiple differing results every time it's run. You may ask yourself what kind of weirdo calls 'new Date()' 20000 times in a row and that hurts a little bit, but I forgive you. More interesting though is what happens when 1000 circ staff open the checkout window 100 times a day; some of them are going to lose this race.

So let's fix it!
$scope.minDate = new Date();

$scope.checkoutArgs = {
    noncat_type : 'barcode',
    due_date : new Date()
};

Problem solved, done and dusted; minDate will be less than due_date no matter how many times you run it, git commit -as -m "Pithy message re: the inexorable march of time." And that's true so long as there's never any other date added that needs to be directly compared to either of these. Oh, and we probably better check maxDate which is also used in a few places also and make certain that compared dates are always declared in the proper order.

Or, at the top of these functions that care about more than 1 date/time we declare a single Date object for "now" and replace every use of new Date() with new Date(now) to copy the same time throughout the function. That way it doesn't matter what order your variables are declared (except that now needs to be first, but 1 positionally relevant variable is definitely better than more than one.)

One last time:
var now = new Date();

$scope.checkoutArgs = {
    noncat_type : 'barcode',
    due_date : new Date(now)
};
// Can't cause date validation failures anymore, even being defined after due_date
$scope.minDate = new Date(now);

Branch on its way.

Revision history for this message
Jason Boyer (jboyer) wrote :
Revision history for this message
Jason Boyer (jboyer) wrote :

Here it is: https://git.evergreen-ils.org/?p=working/Evergreen.git;a=shortlog;h=refs/heads/user/jboyer/lp1864056_reuse_dates / working/user/jboyer/lp1864056_reuse_dates

Because of the nature of the issue it turns out that the only places it can pop up at present are in the circ app of the AngularJS client, so it's a small patch.

Testing is tricky since it's hard to cause the problem to happen in the first place, but if you apply this patch and everything works as expected when checking out, renewing, and viewing items out that means that nothing was broken, anyway.

tags: added: pullrequest
Changed in evergreen:
milestone: none → 3.3.7
milestone: 3.3.7 → none
Revision history for this message
Jennifer Bruch (jbruch) wrote :

Is the attached screenshot of how this error presents itself? Thanks

Jason Boyer (jboyer)
Changed in evergreen:
importance: Undecided → High
Revision history for this message
Jason Boyer (jboyer) wrote :

That's it, Janet. Sometimes a second ticks over between setting the date used for the backdate selector and "now" so the backdate validation fails because the selector is set very slightly in the past.

Revision history for this message
Galen Charlton (gmc) wrote :
tags: added: signedoff
Galen Charlton (gmc)
Changed in evergreen:
status: New → Confirmed
milestone: none → 3.5.0
Changed in evergreen:
milestone: 3.5.0 → 3.5.1
Revision history for this message
Jane Sandberg (sandbergja) wrote :

Good fix. Thanks, Jason and Galen. Pushed to master, rel_3_5, and rel_3_4. I didn't add to rel_3_3, since I wasn't sure that we are doing any more bugfix releases in that series.

Changed in evergreen:
status: Confirmed → Fix Committed
Changed in evergreen:
status: Fix Committed → Fix Released
To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.