[MinGW/Boost.Thread] Segfault multi-threading

Segfault multi-threading [MinGW/Boost.Thread] - C++ - Programmation

Marsh Posté le 12-11-2004 à 23:43:30    

J'ai un leger soucis avec mon code. Lorsque je le fais tourner à fond (100%cpu), une exception (n°5 d'apres le rapport) se déclenche apres environ 10 minutes. Ce qui doit correspondre au segfault.
 
Mon code est compilé/linké en release avec le libs Boost en version release. Il n'y aucune IHM. J'ai l'impression que l'anomalie tourne autour de cet objet :

Code :
  1. template< typename X >
  2. struct bounded_fifo : private boost::noncopyable
  3. {
  4.     fifo( const int& n ) :
  5. begin( 0 ),
  6. end( 0 ),
  7. buffered( 0 ),
  8. circular_buf( n )
  9. {
  10. }
  11.     void write( const X& m )
  12. {
  13.         lock lk( monitor );
  14.         while ( buffered == circular_buf.size() )
  15.             buffer_not_full.wait( lk );
  16.         circular_buf[ end ] = m;
  17.         end = ( end + 1 ) % circular_buf.size();
  18.         ++buffered;
  19.         buffer_not_empty.notify_one();
  20.     }
  21.     X read()
  22. {
  23.         lock lk( monitor );
  24.         while ( buffered == 0 )
  25.             buffer_not_empty.wait( lk );
  26.         X i = circular_buf[ begin ];
  27.         begin = ( begin + 1 ) % circular_buf.size();
  28.         --buffered;
  29.         buffer_not_full.notify_one();
  30.         return i;
  31.     }
  32. private:
  33.     unsigned int begin, end, buffered;
  34.     vector< X > circular_buf;
  35.     condition buffer_not_full, buffer_not_empty;
  36. mutex monitor;
  37. };


Message édité par xterminhate le 14-11-2004 à 20:59:20

---------------
Cordialement, Xterm-in'Hate...
Reply

Marsh Posté le 12-11-2004 à 23:43:30   

Reply

Marsh Posté le 13-11-2004 à 00:01:09    

Je ne vois pas (pis j'ai mangé trop de gateau, ça ralentit le cerveau). Ceci dit, tu fais un notify alors même que tu as encore le lock, donc ça peut lui déplaire et te causer des trucs étranges.  
 
Peux-tu essayer comme ça:

Code :
  1. void write( const X& m )
  2. {
  3. {
  4.        lock lk( monitor );
  5.         while ( buffered == circular_buf.size() )
  6.             buffer_not_full.wait( lk );
  7.         circular_buf[ end ] = m;
  8.         end = ( end + 1 ) % circular_buf.size();
  9.         ++buffered;
  10. }
  11.         buffer_not_empty.notify_one();
  12.     }
  13.     X read()
  14. {
  15. {
  16.         lock lk( monitor );
  17.         while ( buffered == 0 )
  18.             buffer_not_empty.wait( lk );
  19.         X i = circular_buf[ begin ];
  20.         begin = ( begin + 1 ) % circular_buf.size();
  21.         --buffered;
  22. }
  23.         buffer_not_full.notify_one();
  24.         return i;
  25.     }


 
A défaut, quel est le type de X, et où le code plante-t-il ?

Reply

Marsh Posté le 13-11-2004 à 00:12:31    

Je realise la modification et je me reviens vers toi.
 
X est un vector<unsigned char>.
 
Je n'ai précisement aucune technique pour le debug de ce type de code à plusieurs threads. Je ne serais donc pas dire ou le code plante...


---------------
Cordialement, Xterm-in'Hate...
Reply

Marsh Posté le 13-11-2004 à 00:21:07    

Tu es sous quel environnement ? (OS, compilo, etc.). Tu as déjà du le dire, mais j'ai une de ces flemmes de chercher... :)

Reply

Marsh Posté le 13-11-2004 à 08:21:26    

Je travaille sous windows Xp sp 2, et je compile avec MinGW 2.0 (gcc3.2).


---------------
Cordialement, Xterm-in'Hate...
Reply

Marsh Posté le 13-11-2004 à 09:28:30    

Si tu as gdb, tu dois être capable d'avoir les frames de ton truc (il le fait sous cygwin, donc sous mingw, ça doit le faire aussi). Pense juste à compiler avec -g.  

Reply

Marsh Posté le 14-11-2004 à 01:01:39    

En effet, MinGW est fourni avec un outil de debug qui remplace DrWatson. Je constate donc que mon code plante systématique à l'appel des composants logiciels de Boost::Thread (mutex et condition). Comme Boost est fiable, j'en déduis que mon compilo a réellement un pb (configuration multi threading peut etre pas activée). JE vais recompiler avec Visual ou autre.
 
A tout hasard, sais tu comment compiler ce type de code sous GCC/MinGW (ligne de commande) ?


---------------
Cordialement, Xterm-in'Hate...
Reply

Marsh Posté le 14-11-2004 à 01:08:50    

moi j'ai jamais compris ces trucs
 
end = ( end + 1 ) % circular_buf.size();
 
si la taille n'est pas un multiple de 2, mieux vaut faire un pauvre if :D, c'est plus rapide.
 
 
file du code compilable (classe + programme de test) tant qu'à faire si tu as des doutes

Reply

Marsh Posté le 14-11-2004 à 01:19:24    

pour moi il n'y a pas besoin de scoper le lock plus que ça, la définition me semble correcte. je dirais même le contraire. une condition est associée à un lock, il faut demander le verrou dessus tant qu'on la manipule

Reply

Marsh Posté le 14-11-2004 à 08:54:30    

C'est bien ce qui m'embête: le code est correct, et je dirais même canonique: c'est typiquement comme ça qu'il faut faire.  
 
Ceci dit, je ne fais pas 100% confiance au couple Boost/Mingw.
 
Donc le truc était de vérifier si ça marchait mieux en laissant le notify prévenir les classes sans que le lock ne soit actionné (pour qu'elles puissent sortir sans encombre du wait() ).
 
Xterm, sous Mingw, as-tu essayé "-pthread -mthreads" comme option de compil ?

Reply

Marsh Posté le 14-11-2004 à 08:54:30   

Reply

Marsh Posté le 14-11-2004 à 10:36:20    

Lam's a écrit :

C'est bien ce qui m'embête: le code est correct, et je dirais même canonique: c'est typiquement comme ça qu'il faut faire.  

pour moi aussi. c'est pour ça que j'aimerais bien avoir du code compilable + main de test qui montre la défaillance

Reply

Marsh Posté le 14-11-2004 à 11:40:56    

Sans modifier le code source, j'ai mis à jour le compilateur. J'ai aussi recompilé le code avec l'option "-mthreads" (btw, l'option "-pthread" n'est pas reconnue). Je n'ai pas recompilé les librairies Boost.Thread (les dll multithread en paritculier). J'ai relinké mon programme.
 
A prendre avec des pincettes (les bugs de ce type sont traitres), le code tourne depuis une heure sans plantage avec 2 ou 3 threads en plus du main.


Message édité par xterminhate le 14-11-2004 à 11:41:12

---------------
Cordialement, Xterm-in'Hate...
Reply

Marsh Posté le 14-11-2004 à 11:47:46    

ça peut ne pas planter tout en violant l'exclusion mutuelle

Reply

Marsh Posté le 14-11-2004 à 17:27:21    

Fous des traces, je pense que ça peut aider.

Reply

Marsh Posté le 14-11-2004 à 20:58:35    

Apres une douzaine d'heure de test intensif, je n'ai pas eu un seul crash. Je respire enfin ! Tout semble fonctionner correctement.  :)  
 
Je conseille donc à ceux qui utilisent MinGW de mettre leur compilateur à jour en téléchargeant les packages individuels. La version de MinGW en une seule archive et celle fournie avec MinGW Studio ne sont pas fiable pour la programmation multithreads.
 
Merci de votre aide.  :jap:


---------------
Cordialement, Xterm-in'Hate...
Reply

Marsh Posté le 14-11-2004 à 21:19:17    

Je viens de voir que tu compilais avec gcc 3.2 ? Tu es tjrs sous gcc 3.2 ? Il me semble avoir lu qq part que cette version était assez moisie (de façon générale les versions entre la 2.96 et la 3.3.1, il me semble que c'est pas génial, qq peut confirmer ? Taz ?).


Message édité par el muchacho le 14-11-2004 à 21:19:38
Reply

Marsh Posté le 14-11-2004 à 21:39:44    

Clair. Je me demande comment j'ai pu coder autant (dont quelques services winNT multithreads) avec cette version antérieure qui semble peu recommandable !


---------------
Cordialement, Xterm-in'Hate...
Reply

Marsh Posté le 14-11-2004 à 21:41:33    

elle l'est pas mais elle a pas vécu très longtemps. t'as qu'à filer ton code, que je teste avec g++-3.3, g++-3.4 et g++-3.5

Reply

Marsh Posté le 14-11-2004 à 21:43:30    

el muchacho a écrit :

Je viens de voir que tu compilais avec gcc 3.2 ? Tu es tjrs sous gcc 3.2 ? Il me semble avoir lu qq part que cette version était assez moisie (de façon générale les versions entre la 2.96 et la 3.3.1, il me semble que c'est pas génial, qq peut confirmer ? Taz ?).


3.0 et 3.1 pas digne de faire du code "commercial", c'est mon avis. C'est surtout les optimisateurs qui étaient vraiment moisis. Et du code fortement STL sans optimisation du compilo, c'est de la bouse. Bref le compilo était presque inutile.
 
Là, je suis sous la 3.3.3 sous cygwin, et ça a l'air correct, à part les messages d'erreur qui sont à se pisser dessus, mais bon on a ce qu'on paye.
 

Reply

Marsh Posté le 14-11-2004 à 21:48:41    

il faut utiliser stlfilt et ça roule. Les messages sont long et verbeux, certes, mais nécessaires à une analyse fine. Même si tu payais, le message ne pourrait pas être meilleur : y a des échecs d'instantiation, il faut affiche le tout déroulé. Je sais pas comment fait VC, mais je vois mal comment on peut simplifier le message sans perdre d'information.

Reply

Marsh Posté le 14-11-2004 à 21:53:17    

Code :
  1. #include <map>
  2. int main()
  3. {
  4.   std::map<int, int&> a;
  5. }


 

Citation :

g++-3.4 map.cpp  
/usr/include/c++/3.4/bits/stl_map.h: In instantiation of `std::map<int, int&, std::less<int>, std::allocator<std::pair<const int, int&> > >':
map.cpp:5:   instantiated from here
/usr/include/c++/3.4/bits/stl_map.h:332: error: forming reference to reference type `int&'
/usr/include/c++/3.4/bits/stl_pair.h: In instantiation of `std::pair<const int, int&>':
/usr/include/c++/3.4/bits/stl_tree.h:135:   instantiated from `std::_Rb_tree_node<std::pair<const int, int&> >'
/usr/include/c++/3.4/bits/stl_tree.h:1064:   instantiated from `void std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_M_erase(std::_Rb_tree_node<_Val>*) [with _Key = int, _Val = std::pair<const int, int&>, _KeyOfValue = std::_Select1st<std::pair<const int, int&> >, _Compare = std::less<int>, _Alloc = std::allocator<std::pair<const int, int&> >]'
/usr/include/c++/3.4/bits/stl_tree.h:565:   instantiated from `std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::~_Rb_tree() [with _Key = int, _Val = std::pair<const int, int&>, _KeyOfValue = std::_Select1st<std::pair<const int, int&> >, _Compare = std::less<int>, _Alloc = std::allocator<std::pair<const int, int&> >]'
map.cpp:5:   instantiated from here
/usr/include/c++/3.4/bits/stl_pair.h:85: error: forming reference to reference type `int&'


 

Citation :

Comeau C/C++ 4.3.3 (Aug  6 2003 15:13:37) for ONLINE_EVALUATION_BETA1
Copyright 1988-2003 Comeau Computing.  All rights reserved.
MODE:strict errors C++
 
"stl_map.h", line 165: error: reference to reference is not allowed
    _Tp& operator[](const key_type& __k) {
       ^
          detected during instantiation of class "std::map<_Key, _Tp,
                    _Compare, _Alloc> [with _Key=int, _Tp=int &,
                    _Compare=std::less<int>, _Alloc=std::allocator<int &>]" at
                    line 5 of "ComeauTest.c"
 
"stl_pair.h", line 44: error: reference to reference is not allowed
    pair(const _T1& __a, const _T2& __b) : first(__a), second(__b) {}
                                  ^
          detected during:
            instantiation of class
                      "std::pair<_T1, _T2> [with _T1=const int, _T2=int &]" at
                      line 98 of "stl_tree.h"
            instantiation of class "std::_Rb_tree_node<_Value> [with
                      _Value=std::map<int, int &, std::less<int>,
                      std::allocator<int &>>::value_type]" at line 195 of
                      "stl_alloc.h"
            instantiation of "_Tp *std::simple_alloc<_Tp,
                      _Alloc>::allocate(size_t) [with
                      _Tp=std::_Rb_tree_node<std::map<int, int &,
                      std::less<int>, std::allocator<int &>>::value_type>,
                      _Alloc=std::alloc]" at line 475 of "stl_tree.h"
            instantiation of "std::_Rb_tree_node<_Value>
                      *std::_Rb_tree_alloc_base<_Tp, _Alloc,
                      true>::_M_get_node() [with _Tp=std::map<int, int &,
                      std::less<int>, std::allocator<int &>>::value_type,
                      _Alloc=std::allocator<int &>]" at line 497 of
                      "stl_tree.h"
            instantiation of "std::_Rb_tree_base<_Tp,
                      _Alloc>::_Rb_tree_base(const std::_Rb_tree_base<_Tp,
                      _Alloc>::allocator_type & ) [with _Tp=std::map<int, int
                      &, std::less<int>, std::allocator<int &>>::value_type,
                      _Alloc=std::allocator<int &>]" at line 659 of
                      "stl_tree.h"
            instantiation of "std::_Rb_tree<_Key, _Value, _KeyOfValue,
                      _Compare, _Alloc>::_Rb_tree(const _Compare &, const
                      std::_Rb_tree<_Key, _Value, _KeyOfValue, _Compare,
                      _Alloc>::allocator_type & ) [with _Key=std::map<int, int
                      &, std::less<int>, std::allocator<int &>>::key_type,
                      _Value=std::map<int, int &, std::less<int>,
                      std::allocator<int &>>::value_type,
                      _KeyOfValue=std::_Select1st<std::map<int, int &,
                      std::less<int>, std::allocator<int &>>::value_type>,
                      _Compare=std::map<int, int &, std::less<int>,
                      std::allocator<int &>>::key_compare,
                      _Alloc=std::allocator<int &>]" at line 105 of
                      "stl_map.h"
            instantiation of "std::map<_Key, _Tp, _Compare, _Alloc>::map()
                      [with _Key=int, _Tp=int &, _Compare=std::less<int>,
                      _Alloc=std::allocator<int &>]" at line 5 of "ComeauTest.c"
 
2 errors detected in the compilation of "ComeauTest.c".

est mieux formaté, mais ne change pas en substance


Message édité par Taz le 14-11-2004 à 21:53:33
Reply

Marsh Posté le 14-11-2004 à 22:11:58    

Taz a écrit :

il faut utiliser stlfilt et ça roule. Les messages sont long et verbeux, certes, mais nécessaires à une analyse fine. Même si tu payais, le message ne pourrait pas être meilleur : y a des échecs d'instantiation, il faut affiche le tout déroulé. Je sais pas comment fait VC, mais je vois mal comment on peut simplifier le message sans perdre d'information.


Y des scripts sympas pour VC++ qui "remplacent" le compilo et qui font l'équivalent d'un stlfilt.  
 
Mais je ne pensais pas à ça, je pensais à la qualité des messages d'erreur sous Forte (facile à parser, clairs, précis à la colonne près), et les espèces de truc que sort g++, plus proche du "syntax error somewhere".
 
Genre, j'ai eu le malheur d'installer wxWidgets qui m'a françisé le truc à moitié:

Citation :

bidule.cpp: Dans function << int main() >>:
bidule.cpp:5: error: erreur d'analyse syntaxique before string constant

Reply

Marsh Posté le 14-11-2004 à 22:13:46    

ouais alors forte, moins je bosse avec, mieux je me porte. c'est antédéluvien.

Reply

Marsh Posté le 14-11-2004 à 22:23:36    

Taz a écrit :

ouais alors forte, moins je bosse avec, mieux je me porte. c'est antédéluvien.


Le front-end est pas mauvais, et l'optimiseur est carrément solide. Par contre, la gestion des templates est catastrophique, c'est clair.  
 
Le template-repository, il ressemble à un truc codé par un stagiaire. :lol:

Reply

Marsh Posté le 14-11-2004 à 22:27:23    

même au niveau du C, c'est la marne. Je sais pas ce que c'est la politique de licence de Forte, mais sur les Solaris surlesquels je bosse, y a tous les gcc récents contre la version de base fournie ...

Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed