Bonjour/Bonsoir/Salut/kikoolol :-)
Je développe un serveur multithreads.
Quand un client se connecte, j'alloue une entité pour lui donc:
struct Client* newclient = malloc (sizeof (struct Client))
Cette structure en fait comporte des infos sur le clients: socket de communication, username, hostname, est authentifié ou pas... etc
Maintenant dans mon architecture, chaque client est géré par 1 thread. 1 thread gère X clients.
Un thread a une "instance" de pool manager qui fait typiquement:
pool_reset();//FD_ZERO, FD_SET... etc
1 2 3
| for each client in thread->clients // thread = thread courrant
if (fd_isready(client))
recv() + process().... |
Maintenant si une erreur survient lors des envoit/reception, donc erreurs sur la socket on appelle la fonction kill_client(), cette fonction ne fait que:
-> Close la socket et le mettre à -1
-> Notifier les clients connectés que celui là s'est barré
donc la structure allouée par le client n'est pas détruite.
Cette structure est libérée lors de l'appel à pool_reset(), si la socket est -1 free() est appelée directement. Donc un client n'est free() que par le thread qui le gère.
Maintenant imaginons un scénario:
Le client A est géré par le thread A
Le client B est géré par le thread B
Thread B recoit "MESSAGE CLIENT_A Salut" du client B
Thread B appel find_user ("CLIENT_A")et donc recoit la struct du client
Thread A détecte un ping timeout chez le client A et appel kill_client()
Thread A pool_reset() libère la mémoire
// a ce moment y'a plus de client A mais le thread B a déjà la struct
Thread B send (client_A_struct, "Salut")===> BOOOOOM Seg fault
Ici j'ai utilisé que deux threads, mais il est à noter que 3threads pourrait faire la même chose que le thread B aussi
Maintenant j'arrive à ma question:
Quelle est la meilleure facon de poser des locks?
et ou allez vous les poser ces locks?
Mes clients sont stockés dans une hashtable... mais honnêtement j'arrive pas à trouver une facon propre de gérer ces cas critiques
Merci pour vos suggestions
Partager