Friday, January 09, 2009

Software bugs – A tale of dates (Zune)

The recent zune fiasco, brought to the fore-front the ever present problem of software bugs. The Zune issue was caused by a bug in the code that reads the hardware timer and returns breaks it down into the date, month, year, minutes, seconds components. See if you can pin-point the issue from the following code:
year = ORIGINYEAR; /* = 1980 */
while (days > 365)
{
    if (IsLeapYear(year))
    {
        if (days > 366)
        {
            days -= 366;
            year += 1;
        }
    }
    else
    {
        days -= 365;
        year += 1;
    }
}

Basically, in a leap year, the code that would determine the year would end up in an infinite loop.

Here is what happens:Zune BSOD The year 2008 is a leap year, which means that it has 366 days.
    So, at 12:00am on Jan 1, 2009, the value of days will become 366. (The year will be 2008, remember this code is used to increment the year).  
    But because 2008 is a leap year, it will enter the first if block of the code. 
           But because the number of days is 366, it will never enter the inner if block that decrements the number of days
                  And hence the Zune will sit in an endless loop, until the timer increments the day to 366. The timer code is accessed during the boot up process of the Zune. So, if you turned on your Zune anytime between 12:00am Jan 1, 2009 and 11:59pm Jan 1, 2009, the Zune would seem like it was stuck on the bootup screen! The problem automatically fixes it-self on Jan 2nd, 2009, as the number of days becomes 367 and the new number of days will become 2 and the year will become 2009. In actuality, the Zune’s timer is based off GMT and based on Microsoft’s press release, you didn’t have to wait for 2nd Jan, but 12pm (noon) on Jan 1st GMT. Can you think of a way to fix the code shown above? Do you know how to check if a year is a leap year or not? Here is C# code for checking for a leap year:

static bool IsLeapYear(int year)
    {
        if ( ((year%4)==0 && (year%100 != 0)) || (year%400 == 0))
            return true;
        return false;
    }
Or just use the in-built method
DateTime.IsLeapYear(int year);
Here are two articles on some famous software bugs: “To err is human, but to really foul things up you need a computer.”  –Paul Ehrlich
ps: Microsoft’s solution for this was to tell Zune owners to wait until Jan 1, 2009 12pm GMT. This means that the bug it-self has not been fixed. Which means that this issue could re-appear in 4 years (2012). But if you are using the Zune, 4 years from now – I think you have bigger problems, than having to worry about not having your zune for 1/2 day.

No comments: