Bonjour à tous :)
J'ai encore un problème étrange pour lequel je n'arrive pas à trouver de documentation...
J'utilise dans mon programme une structure server_t avec plein de choses dedans. J'ai fait une collection de fonctions ServerFaitQuelqueChose pour modifier cette structure. Pour plus de confort, et étant donné qu'il ne peut n'y avoir qu'une structure server_t fonctionnelle à la fois, j'ai déclaré un pointeur global appelé this qui pointe dessus. Auparavant, quand tout allait bien, tout ceci se trouvait dans un même fichier server.c, qui était devenu assez volumineux.
J'ai donc nettoyé mon code et éparpillé mes fonctions ServerBidule dans divers fichiers suivant ce qu'elles faisaient, et j'ai donc modifié la déclaration de this en conséquence : avant, j'utilisais static server_t *this = NULL dans mon server.c, maintenant j'ai extern server_t *this; dans mon server.h et server_t *this = NULL; dans mon server.c. Tous les fichiers contenant des fonctions ServerMachin #includent "server.h".
Mais là où les choses se corsent, c'est que mon programme ne marche plus correctement depuis. Il compile, il tourne, mais ce que font les fonctions externes ServerTruc n'est plus répercuté sur la structure.
Par exemple, l'une d'entre elle est sensée me charger un plugin et créer des sockets, tous stockés dans des tableaux dynamiques au sein de la structure server_t. A la fin de la fonction, qui tourne sans anicroche, je fait un printf sur this->iSocketCount, ça affiche 1 : cohérent. Dans mon thread serveur (codé dans le fichier où est déclaré this), je fais un printf sur la même variable et il m'affiche triomphalement 0... Là, je ne saisis pas... O_o'
Je vous serais vraiment reconnaissant si vous pouviez me dire ce qui ne vas pas :)
# Thread ou processus ?
Posté par pierthi . Évalué à 2.
Déjà la programmation multi-threadée, ce n'est pas marrant à débugger lorsqu'on a les sources, alors quand on ne les a pas, difficile de dire ce qui ne va pas.
A priori, vérifie encore l'adresse de "this" dans les deux modules. Ils ne devraient pas différer, mais puisque tu obtiens deux valeurs différentes, ce me semble être la seule explication possible. Et le seul cas où ça peut arriver, c'est lorsqu'on utilise des processus et non des threads.
Tu n'aurais pas un lien sur tes sources ?
[^] # Re: Thread ou processus ?
Posté par JaguarWan . Évalué à 1.
http://membres.lycos.fr/jaguar_agency/(...)
Je ne peux pas linker le fichier directement, il faut utiliser le lien Source sur la page.
Le programme est loin d'être fini, j'espère que ça compilera chez toi.
Il y a un makefile pour compiler le serveur, on peut tester les sockets en compilant les programmes de test dans net/test.
Il faut que le plugin standard soit compilé, s'il ne l'est pas il y a un makefile dans plugin/standard.
Voilà voilà, si tu vois des horreurs en passant n'hésites pas à m'en faire part :)
[^] # Re: Thread ou processus ?
Posté par JaguarWan . Évalué à 1.
ls [plugin|socket] pour voir les sockets/plugins actifs
plugin [open|close] [nom de fichier] pour charger/décharger un plugin
exit pour quitter proprement
[^] # Mouais ...
Posté par pierthi . Évalué à 3.
Le problème se situe dans la fonction ServerAlloc() : tu analyses ton fichier de configuration (mm.conf) qui positionne iPluginCount et iSocketCount puis quelques lignes après (toujours dans ServerAlloc) tu remets ces 2 variables à 0.
J'ai essayé de remonter l'affectation des variables, mais ça segfault.
PS: gdb est ton ami dans ces cas là (et un bon stock d'aspirine aussi).
[^] # Re: Mouais ...
Posté par JaguarWan . Évalué à 1.
Merci beaucoup, j'ai déplacé la lecture du script et ça marche mieux maintenant :)
[^] # Re: Thread ou processus ?
Posté par forc3 . Évalué à 4.
1) utilisation de select, donc de ses limitations, alors que tout
est dynamique ->dommage pas scalable, et limité en nombre de fd.
Pourquoi utiliser nap() et appeler également select() au début de
la boucle ? Pourquoi appeler FD_ZERO à chaque fois alors que il
suffit d'avoir un FD_SET déjà initialisé qui remettrait à 0
'setSockets' ?
FD_ZERO(&blankSockets)
while ()
setSockets = blankSockets;
(mm_net_server.c) (mm_net_nap.c)
2) remplacer tous les appels à strncpy par memcpy...
2) le connect est bloquant, penser a mettre le fd on O_NONBLOCK et
gerer le EINPROGRESS... Idem pour accept. (mm_net_socket.c)
3) Le type string_t est nase, il aurait fallu avoir un unsigned int
en plus dans la structure contenant le nombre exacte de bytes
disponibles différent de la longeur de la string véritable, et
allouer toujours un peu plus que necessaire. (mm_core_string.c)
4) trop de semaphore.
5) trop d'allocation mémoire dans tous les sens, penser à faire des
pool ou alors allouer les maximums d'objets au début. Malloc est le
point noir de toute application.
Les threads c'est bien pour ne pas se prendre la tête à faire
mieux. Mais pour un serveur c'est pas vraiment le top...
http://www.kegel.com/c10k.html(...)
[^] # Re: Thread ou processus ?
Posté par JaguarWan . Évalué à 1.
J'ai utilisé select() dans nap() car c'est la seule fonction que j'ai trouvé qui permet de faire un sleep() de moins d'une seconde présente sous Linux et Windows.
Merci pour tous ces conseils en tout cas :)
[^] # Re: Thread ou processus ?
Posté par SoWhat . Évalué à 2.
- s'il y a des données à lire, on les lit et on recommence tout de suite
- s'il n'y a pas de données, de toute façon le select ne rend pas la main et équivaut à un nap.
[^] # Re: Thread ou processus ?
Posté par forc3 . Évalué à 1.
Je veux dire par exemple AsyncSelect ou un truc du genre sous windows.
Maintenant si ton programme est prévu pour supporter une lourde charge, je pense
qu'il faut l'adapter a la plateforme.
Penser Thread pour win et faire un choix sous linux entre Thread ou Automate...
Apres choisir une bon implem de thread.
Le top reste la possibilité de changer facilement le moteur afin d'avoir juste une
modification minime a effectuer pour utiliser la fonction propre au systeme.
Et du coup réaliser des benchs et enfin faire un choix...
[^] # Re: Thread ou processus ?
Posté par SoWhat . Évalué à 3.
mais select, ça reste portable. epoll, c'est bien , mais faut un kernel 2.6, et les autres trucs c'est pas pour linux... ça ne laissa pas beaucoup de choix tout ça. faudra que j'aille voir de plus près les implémentations.
# recompilation
Posté par gaaaaaAab . Évalué à 3.
Chez moi, ça compile sans souci, et quand je passe dans gdb, une fois que j'ai chargé le plugin libstd.so, tous les thread voient bien this->iPluginCount et this->iSocketCount à 1 (Si j'ai bien compris, c'est là que ça bloque chez toi).
Le seul truc, c'est un vilain SIGSEV au moment du exit, mais j'ai pas réussi à voir d'ou il sort, et la, il commence à être tard.
je tenterais bien avec un valgrind ou un mpatrol ...
sinon, quelque remarques sur la forme:
pourquoi les fichiers sources ils sont exécutables ?
il manque le -g dans le makefile du répertoire racine.
En fait, les CFLAGS, je la mettrais plutot dans une variable d'environnement externe pour pas être obligé de modifier tous les makefile dès qu'on veut rajouter une option de compil
pourquoi ne pas tirer partie des règles de compilation implicite de make
genre
au lieu d'une tripotée de cibles du genre
on peut aussi remplacer
par
et si on est super motiv, on remplace tous les appels récursifs à make
par des inclusions de make (cf
http://www.tip.net.au/~millerp/rmch/recu-make-cons-harm.html(...) pour le pourqoi)
[^] # Re: recompilation
Posté par gaaaaaAab . Évalué à 3.
[^] # Re: recompilation
Posté par JaguarWan . Évalué à 1.
J'ai réécrit un makefile plus propre, merci pour tes indications :)
Suivre le flux des commentaires
Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.