Je trouve qu’il y a une assez grande confusion autour de ce bogue, son origine, si c’est normal ou pas et ses conséquences aujourd’hui ou demain.
Reprocher qu’à l’époque on utilise un entier signé sur 32 bits pour représenter le temps, c’est méconnaître grandement l’impact en performance d’un autre choix. Tout comme certains qui regrettent les nombres flottants par rapport au calcul multiprécision. Ne pas oublier que ce sont des données manipulées en permanence (de nombreux programmes font des appels systèmes liés à la date des milliers de fois par seconde). Il faut qu’on puisse le traiter vite et utiliser le type natif du processeur offrait un bon compromis performance / longévité. Et bien entendu cette donnée étant générée par le noyau de votre système d’exploitation, n’espérez pas un comportement de haut niveau avec des données très abstraites. Ne pas oublier également qu’UNIX (et la norme POSIX) ont une longévité record. Vous connaissez des API et des OS aussi vieux tout en étant largement utilisés ? En réalité, il n’y en a pas vraiment. Je doute très fortement que quiconque à l’époque aurait prédit un tel succès.
Ce n’est donc pas un mauvais design, comme tout en informatique, cela résulte d’un compromis qui a été longuement efficace. Et il était assez invraisemblable au moment de la définition que POSIX et l’architecture 32 bits pourraient coexister jusqu’à cette échelle de temps.
Corriger le problème pour des machines compatibles POSIX avec une architecture 32 bits sous-jacente n’est pas aisée si on s’inquiète de la stabilité de l’ABI, ce qui est le cas de Linux. À dire vrai il existe déjà des appels systèmes qui utilisent des entiers 64 bits pour de telles architecture mais cela demande du code spécifique et donc de recompiler les programmes concernés ce qui n’est pas toujours possible. Et cela est moins portable (non compatible POSIX de souvenir).
L’idée est d’essayer de mettre des wrappers dans le noyau et la glibc pour contourner plus ou moins le soucis. En tout cas ce n’est pas simple et malgré des années de travaux nous sommes encore loin d’une solution parfaite (de nombreuses structures fournies par le noyau, dont via les ioctl
utilisent le fameux type time_t
source de tous les maux.
Travaillant dans l’embarqué, on débute des projets dont la durée de vie est de 10-15 ans avec de l’ARM 32 bits, on commence donc à toucher l’horizon des temps du fameux bogue. Et bien entendu dans l’aérospatial, militaire, automobile, ferroviaire ou aéronautique cela est probablement déjà atteint ce qui n’est pas sans poser de soucis à terme.
Allons tester nos applications ! Je serais curieux de connaitre les vrais effets problématiques de ce bug dans la pratique.
Bah exemple tout con, mon projet actuel est un collecteur de capteurs qui assigne donc à chaque mesure une date précise en temps réel. Et pour des raisons de performances, ARM 32 bits tout ça, time_t
est un 32 bits signé. Si jamais la date du bogue 2038 est atteinte, bah j’aurais une date fausse et le serveur en face aura bien du mal à m’afficher la donnée à la date attendue.
Et je passe outre certains codes (un peu sale), où il font de la différence de temps pour calculer des timeout. Le temps d’attente risque d’être bien long une fois ce seuil franchi…
Dans ma tête c’était un INT UNSIGNED, je n’avais jamais vu qu’on pouvait utiliser un nombre négatif pour aller avant 1970.
De souvenir POSIX ne définie pas vraiment le type de time_t
. C’est au choix du compilateur / système. Mais autoriser un nombre négatif n’est pas forcément idiot, soit pour permettre en effet un espace de temps plus large que celui proposé par défaut dans le passé. Ou pour faire passer des erreurs. Ou pour faire des comparaisons de temps (une différence de temps qui retourne une valeur négative).
Dans POSIX c’est de toute façon assez rare l’usage des unsigned int
, le type entier est très souvent préféré pour des raisons de souplesses et de performances.