Quels que soient les logiciels utilisés, tout le monde a un jour ou l'autre été confronté à un bug informatique. Du
freeze d'un programme aux pertes de données, les bugs sont un fléau que tout bon développeur se doit d'éradiquer pour contenter les utilisateurs. Développé par l'
EPFL, Dimmunix est un projet qui entend révolutionner cette approche, en permettant à l'ordinateur d'éviter lui-même les bugs.
Dans sa dernière version, gratuitement téléchargeable, il se base sur le principe du
cloud computing pour permettre de protéger une ferme de serveurs entière, en partageant les informations entre ceux-ci.
Le principe de Dimmunix
Le concept est inspiré de notre système immunitaire humain. Lors d'une infection, notre corps produit en effet des anticorps, qui seront alors capables de reconnaître à nouveau le facteur infectieux lors d'une future attaque. George Candea, directeur du projet, présente Dimmunix comme une application de ce principe aux programmes informatiques : lorsqu'un logiciel plante à cause d'un bug particulier, celui-ci est sauvegardé, et Dimmunix tente de l'éviter par la suite.
En fait, Dimmunix ne permet pour le moment d'éviter que certains bugs, appelés deadlocks ou
interblocage en français. Ces interblocages peuvent survenir en programmation concurrente, quand un même logiciel utilise plusieurs
processus, en parallèle, c'est à dire quand certaines instructions sont exécutées simultanément (ou que l'on considère qu'elles le sont). Pour que ceci soit possible, on met en place des verrous sur les ressources système, de manière à ce qu'il n'y ait pas de conflits lorsque les processus demandent simultanément l'accès à ces ressources. Cependant il peut arriver qu'un processus bloque une ressource A et demande une ressource B, pendant qu'un autre processus bloque la ressource B et demande la ressource A.
Évidement dans ce cas les deux processus se retrouvent bloqués indéfiniment, et le programme également : c'est à ce niveau que doit agir Dimmunix. Pour cela, un processus est chargé de surveiller l'exécution du programme. Lorsque celui-ci détecte un interblocage, il renseigne le
Resource Allocation Graph, qui garde un historique des obtentions et relâchements de verrous avant l'interblocage, pour créer ensuite ce que l'on appelle la signature. Cette signature permettra à Dimmunix de prévenir l'interblocage dans le futur si la même situation est détectée. Si ce programme est surtout fait pour les serveurs, il est cependant tout à fait utilisable par un utilisateur quelconque et pour n'importe quelle application (Dimmunix a par exemple été testé sur Limewire).
Le RAG, ou Ressource Allocation Graph
Le RAG est un graphe (une sorte de schéma) qui résume l'ensemble des interactions entre les processus et les verrous. Il est construit pour représenter les différents évènements qui se déroulent pendant que le logiciel étudié tourne : le premier correspond à la demande d'accès à un verrou par un processus ; le deuxième au fait que Dimmunix autorise ce processus à faire une pause en attendant d'obtenir un accès ; un autre indique que le processus obtient effectivement l'accès. Le dernier type d'évènement possible correspond au fait qu'un processus cède sa place à un autre. Ce graphe permet à Dimmunix de détecter des structures cycliques, qui sont le signe d'un interblocage.
À partir de la détection de ce cycle, le programme est arrêté, mais il faut que Dimmunix enregistre une signature de manière à empêcher cet interblocage de survenir de nouveau. Cette signature est en fait constituée des numéros de toutes les évènements représentés sur le graphe, indiquant soit l'accès à un verrou par un processus, soit l'arrêt d'un processus en faveur d'un autre. Elle est stockée dans un fichier, et c'est elle qui va permettre à Dimmunix d'empêcher l'interblocage par la suite.
Empêcher les bugs de survenir à nouveau
Une fois la signature enregistrée, il faut faire en sorte d'éviter que le bug survienne de nouveau. Pour cela, toutes les requêtes d'accès aux verrous sont interceptées par Dimmunix, qui va ensuite indiquer au processus si celui-ci peut se bloquer en attendant la ressource, ou s'il doit laisser la main à un collègue (donc cesser de tourner jusqu'à ce que ce collègue libère la ressource). Pour cela, il consulte son historique, et cherche si le fait d'attendre la ressource peut amener le programme dans une situation d'interblocage. S'il trouve une signature qui correspond à la situation courante, il ordonne alors au processus qui fait la requête de laisser la main à un autre processus de manière à libérer la ressource.
D'un serveur à toute une ferme
La dernière version de Dimmunix généralise ce principe à un ensemble de serveurs : chaque machine faisant tourner un logiciel surveillé par Dimmunix est en quelque sorte capable de communiquer avec les autres pour partager les rapports d'erreurs, ainsi que les solutions. Ainsi, si un interblocage est détecté sur un serveur, tous les autres seront protégés, comme un vaccin que l'on injecterait à toute une population.
Un test concret
On peut écrire un petit programme en C pour tester le fonctionnement de Dimmunix :
Secret (cliquez pour afficher)Code : C 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49 | #include <pthread.h>
#include <unistd.h>
#include <stdio.h>
pthread_mutex_t mutex1;
pthread_mutex_t mutex2;
void f1() {
pthread_mutex_lock(&mutex1);
sleep(1);
pthread_mutex_lock(&mutex2);
pthread_mutex_unlock(&mutex2);
pthread_mutex_unlock(&mutex1);
printf("thread 1 done\n");
}
void g1() {
pthread_mutex_lock(&mutex2);
sleep(1);
pthread_mutex_lock(&mutex1);
pthread_mutex_unlock(&mutex1);
pthread_mutex_unlock(&mutex2);
printf("thread 2 done\n");
}
void* f(void* args) {
f1();
}
void* g(void* args) {
g1();
}
int main() {
pthread_mutex_init(&mutex1, 0);
pthread_mutex_init(&mutex2, 0);
pthread_t t1;
pthread_t t2;
pthread_create(&t1, NULL, f,
NULL);
pthread_create(&t2, NULL, g,
NULL);
pthread_join(t1, NULL);
pthread_join(t2, NULL);
}
|
Ce code reproduit en effet la situation énoncée en début de news et aboutit à un interblocage. Lançons le programme, compilé sous le nom de "test", sans oublier de précharger Dimmunix :
$ LD_PRELOAD=../src/libdimmunix.so ./test
Et l'on obtient :
deadlock found and saved to dlock.history
Complété
Cela signifie que le programme a effectivement buggé, et que Dimmunix l'a détecté. Le fichier dlock.history doit contenir le nécessaire pour éviter que l'interblocage ne se reproduise. On teste donc une seconde fois :
$ LD_PRELOAD=../src/libdimmunix.so ./test
Et l'on obtient cette fois :
thread 1 done
thread 2 done
Le programme a donc correctement fonctionné, et ce sans qu'il soit nécessaire de le modifier ou même de le recompiler. Tout est fait de manière automatique par Dimmunix, qui s'occupe d'ordonnancer l'attribution des verrous de manière à éviter l'interblocage détecté précédemment.
Un projet prometteur
Dimmunix est une petite révolution dans le monde des bugs informatiques. Cependant il ne faut pas perdre de vue que le programme peut aussi détecter de faux positifs (c'est à dire croire à un interblocage alors qu'il n'y en a pas). Ceci n'est pas très grave en soi, et ne porte pas atteinte à l'exécution générale du programme, mais peut causer des ralentissements inutiles. Bien sûr, la meilleure solution pour éviter ce genre de bugs est de s'en préoccuper lors de la conception du programme : même si les interblocages sont parfois difficiles à éviter, on trouve généralement une solution.
Dimmunix permet cependant de pallier le problème temporairement, en attendant que les développeurs du logiciel buggé corrigent leur code. Il permet également dans ce cas-là de faire remonter aux développeurs l'historique enregistré, pour les aider à comprendre la situation. Le fait que le projet soit désormais jugé utilisable pour des vrais serveurs est très prometteur, puisqu'il a déjà été testé avec succès sur des projets variés comme MySQL, Apache, Limewire ou ActiveMQ.
Liens
49 Participations
Connectez-vous !
Connectez-vous !
Revenir à la liste des news