2010-06-10 5 views
1

J'ai besoin de gérer le SIGSEGV dans mon application Linux. La raison en est que le nettoyage (3-partry lib) doit être fait avant de générer core-dump. Qui plus est, le nettoyage doit être effectué dans le contexte d'un thread appelant, impossible à faire dans le gestionnaire de signal. Donc, je prévois dans le gestionnaire de signal de passer le contrôle au thread appelant, une fois le nettoyage terminé, puis utilisez raise (SIGSEGV) pour générer le core-dump.gérer SIGSEGV sous Linux?

Le vrai problème semble que le signal_handler ne peut pas passer le contrôle à un thread appelant, peu importe que j'utilise post_sem ou d'autres. Une idée pour gérer ce cas? Peut-on détourner le SIGSEGV, puis dans SIGSEGV, le hander revient à un autre thread pour effectuer un nettoyage?

signal (SIGSEGV, signal_handler);

signal_handler() { ... post_sem(); ...}

thread appelant() { de wait_sem(); clean_up(); ...}

+0

La méthode que vous avez décrite est en réalité la chose la plus proche de valide. 'sem_post' (la version POSIX) est requis par le standard pour être sans danger pour le signal asynchrone. –

Répondre

2

Ce ne est pas possible de fiable exécution de code après avoir rencontré un SIGSEGV. Vous pourriez vous en tirer parfois mais vous ne pouvez pas faire confiance à votre programme pour fonctionner comme prévu par la suite. Si, par exemple, vous avez un SIGSEGV à cause d'un tas corrompu, vous aurez des problèmes si votre libraire tiers nettoie la mémoire.

Pour obtenir une solution fiable, je voudrais savoir si vous avez vraiment besoin d'exécuter ce code de nettoyage ou s'il y a une autre façon de gérer la situation (vérifier un arrêt non propre au prochain démarrage, ...).

1

Je pense que vous ne devriez pas essayer d'exécuter quoi que ce soit qui nettoie l'état de la mémoire, en particulier en l'écrivant sur le disque, comme si elle réussissait, vous causeriez une corruption des données.

L'enregistrement de certaines informations d'état, si possible, peut faciliter le débogage, mais vous ne devriez pas vous en douter. Au lieu de cela, le programme devrait, après la journalisation des informations d'état, soit revenir au gestionnaire par défaut (et vider le noyau, etc.), soit appeler _exit et quitter sans aucun nettoyage.

Si vous devez effectuer un nettoyage pour redémarrer après un plantage, faites-le au prochain démarrage.

3

Vous voulez nettoyer après un SIGSEGV (erreur sérieuse) ... Je trouve cela un peu bizarre parce que, 1) si vous étiez en train de déboguer l'application, vous devriez tout laisser intact pour être stocké dans le fichier core afin que vous puissiez identifier avec précision ce qui s'est passé et 2) si vous avez une application de sortie pour un client (disons) bien ... il ne devrait pas SIGSEGV :) (pas mon problème de toute façon, juste dire ..)

Sur le sujet,

Je pense que vous pourriez essayer de bloquer SIGSEGV dans tous les threads à l'exception de celui dans lequel vous essayez de faire le nettoyage; cela devrait faire que le système envoie le signal à ce fil spécifique. Une autre solution que je pourrais penser est quelque chose sur le modèle de setjmp()/longjmp() (n'en ai testé aucun). Faites attention qu'une fois que votre programme a obtenu un SEGV, vous êtes sur un terrain instable (c'est-à-dire que votre nettoyage pourrait échouer aussi bien et générer un autre SEGV etc.) donc vous devriez envisager de vous écraser avec un noyau.

+0

N'aidera pas. 'SIGSEGV' est livré au thread spécifique qui a causé l'accès invalide, pas le processus dans son ensemble. –