Le Zune 30, triple baffe, et la bonne résolution de 2009

En cette fin d'année 2008, j'ai suivi avec attention les aventures des possesseurs de Zune 30 et la (légère) ébullition de la communauté concernant le bug qui faisait crasher certains players mp3 de chez Microsoft et Toshiba le 31 décembre 2008, ces mêmes players ressucitant le jour suivant, pour peu que la batterie ait été vidée. Non pas parce que j'ai un Zune 30, mais parce que ce bug pour moi c'est pire que Kiss-Cool, c'est triple effet:

  • le Zune 30 plante, et qu'en tant que Microsoftee (et utilisateur de Zune), ca ne fait pas plaisir.
  • Parce que le bug vient d'un driver Freescale, mon ancien employeur, et que donc ca fait encore moins plaisir (même si ca n'est pas moi qui ait écrit ce bout de code)
  • Parce que ca risque d'affecter tous les devices qui utilisent Windows Embedded CE 5.0 avec ce driver Freescale.

Dans le code d'un système embarqué utilisant Windows Embedded CE, on ne retrouve en effet pas que du code Microsoft. La plus grande partie des drivers est écrite par les fabricants de semiconducteurs (les microprocesseurs surtout) d'une part, et les intégrateurs qui adaptent ces drivers à l'électronique "autour" de ces microprocesseurs d'autre part: c'est pour cela que Microsoft distribue 100% des sources du kernel et la plus grosse majorité des sources des drivers "partagés" et des des applications.

Je ne dis pas ça pour désigner un coupable ou décharger Microsoft de certaines responsabilités (tout le monde écrit du code buggé), mais pour qu'on comprenne bien la mécanique sous-jacente, et donc qui risque d'être affecté par ce bug: à savoir, les gens qui:

  • utilisent Windows Embedded CE 5.0 (la version actuelle est la 6.0 R2)...
  • ... avec le MC13783 de Freescale...
  • ... et le driver de la RTC (Real Time Clock) de ce chip.

Le bug n'apparait pas:

  • si on n'utilise pas le MC13783
  • ou si on l'utilise sans la RTC
  • ou si on utilise la dernière version de Windows Embedded CE 6.0 R2, car le bug n'existe pas dans le BSP Freescale pour cette version.

Pour ceux qui seraient touchés, la correction du bug est très simple: le fichier mis en cause est C:\WINCE500\PLATFORM\COMMON\src\ARM\FREESCALE\PMIC\MC13783\RTC\rtc.c

Le code incriminé est dans la fonction ConvertDays du coté de la ligne 230. Regardez la boucle suivante en imaginant que la variable days vaut 366

while (days > 365)
{
if (IsLeapYear(year))
{
if (days > 366)
{
days -= 366;
year += 1;
}
}
else
{
days -= 365;
year += 1;
}
}

Boum, si days == 366, boucle infinie. C'est ça le bug et c'est pour cela qu'il se résout automatiquement le jour suivant. Mais le problème risque de se reproduire à la fin de la prochaine année bissextile et si d'ici là les Zune 30 seront probablement relayés au rang d'antiquités, certains équipements professionnels seront encore affectés: il faut donc fixer le bug et la solution est simple:

    while (days > 365)
{
if (IsLeapYear(year))
{
if (days > 366)
{
days -= 366;
year += 1;
}
else
{
break;
}
}
else
{
days -= 365;
year += 1;
}
}

et la solution la plus élégante que ce soit pour les performances ou la stabilité:

    int daysThisYear = (IsLeapYear(year) ? 366 : 365);
//The number of days in the current year is now calculated instead.
while (days > daysThisYear)
{
days -= daysThisYear;
year += 1;
daysThisYear = (IsLeapYear(year) ? 366 : 365);
}

Quelles conclusions tirer de ce bug?

  • Nul n'est à l'abri d'écrire du mauvais code
  • On ne sait jamais qui réutilisera le code et il n'existe pas de code "non important" dans un device embarqué
  • Il faut donc faire très attention à sa couverture de test et à la façon dont on écrit son code, surtout la gestion des erreurs, des conditions, et des boucles!
  • Et enfin la publication du code source aide à la compréhension et la résolution des bugs et c'est pour ça que le code de Windows Embedded CE est livré sous licence Shared Source

Les liens intéressants:

Et la bonne résolution 2009: Essayer d'écrire du code propre (et le tester correctement!)