2010-02-22 4 views
1

J'ai une application liée à libpthread. Le noyau de l'application est constitué de deux FIFO partagées par quatre threads (deux threads par FIFO). La classe FIFO est synchronisée à l'aide de mutex pthread et stocke des pointeurs vers de grandes classes (contenant des tampons d'environ 4kb) allouées dans la mémoire statique en utilisant des opérateurs new et delete surchargés (aucune allocation dynamique ici).Segfaults du programme libpthread C++ pour une raison inconnue

Le programme lui-même fonctionne généralement bien, mais de temps en temps il se sépare sans raison apparente. Le problème est que je ne peux pas déboguer les segfaults correctement car je travaille sur un système embarqué avec un ancien noyau linux (2.4.29) et g ++ (version gcc egcs-2.91.66 19990314/Linux (egcs-1.1. 2 version)).

Il n'y a pas de gdb sur le système, et je ne peux pas exécuter l'application ailleurs (elle est trop spécifique au matériel).

J'ai compilé l'application avec les drapeaux -g et -rdynamic, mais un gdb externe ne me dit rien quand j'examine le fichier core (seulement les adresses hexadécimales) - je peux toujours imprimer le backtrace du programme après avoir attrapé SIGSEGV - toujours ressemble à ceci:

Backtrace for process with pid: 6279 
-========================================- 
[0x8065707] 
[0x806557a] 
/lib/libc.so.6(sigaction+0x268) [0x400bfc68] 
[0x8067bb9] 
[0x8067b72] 
[0x8067b25] 
[0x8068429] 
[0x8056cd4] 
/lib/libpthread.so.0(pthread_detach+0x515) [0x40093b85] 
/lib/libc.so.6(__clone+0x3a) [0x4015316a] 
-========================================- 
End of backtrace 

il semble pointer vers libpthread ...

J'ai couru quelques-uns des modules par valgrind, mais je ne trouve pas de fuites de mémoire (comme je suis à peine en utilisant n'importe quelle allocation dynamique).

Je pensais que peut-être les mutex causent des ennuis (car ils sont verrouillées/déverrouillées à environ 200 fois par seconde) alors je suis passé ma classe simple mutex:

class AGMutex { 

    public: 

     AGMutex(void) { 
      pthread_mutex_init(&mutex1, NULL); 
     } 

     ~AGMutex(void) { 
      pthread_mutex_destroy(&mutex1); 
     } 

     void lock(void) { 
      pthread_mutex_lock(&mutex1); 
     } 

     void unlock(void) { 
      pthread_mutex_unlock(&mutex1); 
     } 

    private: 

     pthread_mutex_t mutex1; 

}; 

à une classe mutex mannequin:

class AGMutex { 

    public: 

     AGMutex(void) : mutex1(false) { 
     } 

     ~AGMutex(void) { 
     } 

     volatile void lock(void) { 
      if (mutex1) { 
       while (mutex1) { 
        usleep(1); 
       } 
      } 
      mutex1 = true; 
     } 

     volatile void unlock(void) { 
      mutex1 = false; 
     } 

    private: 

     volatile bool mutex1; 

}; 

mais il n'a rien changé et la trace a la même ...

Après quelques oldchool mis-cout entre-chaque ligne et voir-où-il-segfaults-plus -remember-the-pids-and-stuff session de débogage il semble que cela se sépare pendant l'endormissement (?).

Je n'ai aucune idée de ce qui pourrait être faux. Il peut travailler pendant une heure ou deux, puis soudainement segfault sans raison apparente.

Est-ce que quelqu'un a déjà rencontré un problème similaire?

+0

Utilisez-vous des attributs de thread? Détacher les threads manuellement –

+0

@Nikolai N Fetissov: Non, c'est juste pthread_create avec NULL passé comme second argument et puis pthread_exit -> pthread_join – zajcev

Répondre

1

De mon answer-How to generate a stacktrace when my gcc C++ app crashes:

 
    The first two entries in the stack frame chain when you get into the 
    signal handler contain a return address inside the signal handler and 
    one inside sigaction() in libc. The stack frame of the last function 
    called before the signal (which is the location of the fault) is lost. 

Cela peut expliquer pourquoi vous avez des difficultés à déterminer l'emplacement de votre segfault via un backtrace d'un gestionnaire de signal. Mon answer inclut également une solution de contournement pour cette limitation.

Si vous voulez voir comment votre application est effectivement mis en mémoire (à savoir 0x80..... adresses), vous devriez être en mesure de générer un fichier carte de gcc. Cela se fait généralement via -Wl,-Map,output.map, qui passe -Map output.map à l'éditeur de liens.

Vous pouvez également avoir une version spécifique au matériel de objdump ou nm avec votre toolchain/cross-toolchain qui peut être utile pour déchiffrer vos 0x80..... adresses.

+0

Merci, je vais essayer ça demain – zajcev

0

Avez-vous accès à Helgrind sur votre plateforme? C'est un outil Valgrind pour détecter les erreurs de threads POSIX telles que les races et les threads contenant des mutex quand ils sortent.