2016-09-23 2 views
6

Lorsque notre programme UNIX/C a besoin d'une sortie de secours, nous utilisons la fonction exit (3) et installons des manipulateurs atexit (3) pour les nettoyages d'urgence. Cette approche a fonctionné correctement jusqu'à ce que notre application ait été enfilée, à quel point les gestionnaires atexit() se sont arrêtés pour fonctionner de manière prévisible.Que dit la norme POSIX à propos des piles de threads dans les gestionnaires atexit()? Quelle est la pratique du système d'exploitation?

Nous avons appris par une erreur que les threads sont déjà morts dans le gestionnaire atexit() et que leurs piles ont été désallouées.

Je n'ai pas trouvé de citation dans la disparition de thread de liaison standard avec atexit(): les threads cessent d'exister après le retour de main(), mais est-ce avant l'invocation de atexit() ou after? Quelle est la pratique actuelle sur Linux, FreeBSD et Mac?

Y a-t-il un bon modèle pour le nettoyage d'urgence dans un programme multi-thread?

Répondre

3

Posix standard

Il ne semble pas être défini par Posix si atexit gestionnaires sont appelés avant ou après les discussions sont terminées par exit.

Il existe deux (ou trois) façons pour un processus de se terminer "normalement".

  • Tous les threads se terminent. Lorsque le dernier thread se termine, en retournant ou en appelant pthread_exit, les gestionnaires atexit sont exécutés. Dans ce cas, il n'y a pas d'autres threads. (Cela dépend de la plate-forme Certaines plates-formes peuvent terminer d'autres threads si le thread principal se termine autre que exit, d'autres pas). Un thread appelle exit. Dans ce cas, les gestionnaires atexit seront exécutés et tous les threads seront terminés. Posix ne précise pas dans quel ordre.

  • main renvoie. Cela équivaut plus ou moins à appeler exit() comme dernière ligne de main, donc peut être traité comme ci-dessus.

OS pratique

Dans Linux, la documentation https://linux.die.net/man/2/exit dit les discussions sont terminées par _exit appelant exit_group, et que _exit est appelé après atexit gestionnaires. Par conséquent, sous Linux, en appelant le exit, tous les gestionnaires atexit sont exécutés avant que les threads ne soient terminés. Notez qu'ils sont exécutés sur le thread appelant exit, pas le thread qui a appelé atexit.

Sous Windows, le comportement est le même, si vous y tenez.

Motifs pour le nettoyage d'urgence.

Le meilleur modèle est: Ne jamais être dans un état nécessitant un nettoyage d'urgence.

  • Il n'y a aucune garantie que votre nettoyage sera exécutée parce que vous pourriez avoir un kill -9 ou une panne de courant.
  • Par conséquent, vous devez être en mesure de récupérer dans ce scénario.
  • Si vous pouvez récupérer à partir d'un cela, vous pouvez également récupérer de abort, de sorte que vous pouvez utiliser abort pour votre sortie de secours.

Si vous ne pouvez pas le faire, ou si vous avez « nice-to-have » nettoyage que vous voulez faire, les gestionnaires atexit devraient être bien fourni vous devez d'abord arrêter gracieusement toutes les discussions dans le processus afin d'éviter entrer un état incohérent pendant le nettoyage.

+0

Je pense que ce cas d'utilisation devrait être noté au comité POSIX/ISO pour discussion. Cela dit, je suis d'accord que vous ne voulez jamais être dans un endroit où vous devez nettoyer, mais je me suis retrouvé dans un tel endroit une ou deux fois - le plus récemment si mon TAP était conforme Le code de test d'unité/de régression déclenche une exception, soit je n'ai pas de sortie de message, soit je dois gérer atexit. Ne pas avoir une définition rigoureuse d'atexit dans le cas de multi-thread pourrait être problématique. – EBo