2012-10-27 1 views
11

Comme indiqué dans http://en.cppreference.com/w/cpp/error/terminate il existe de nombreuses raisons d'appeler se terminer. Je peux imaginer le cas où presque dans le même temps certaines de ces raisons se produisent dans deux fils.La fonction terminate() doit-elle être thread-safe?

Q1 peut la fin fonction définie par std::set_terminate être appelé deux fois ou plus en même temps, en même temps, je veux dire deuxième appel commence avant la première a pris fin.

Thread1 Thread2 
    |   | 
    _   | 
    t   | 
    e   | 
    r   | 
    m   | 
    i   _ 
    n   t 
    a   e 
    t   r 
    e   m 
    -   ? 

Q2 Si Q1 == OUI, alors ce qui se passe si Achever d'abord pris fin. Je suppose que si cela se terminait par std :: abort, alors le programme se termine, mais que se passe-t-il si l'utilisateur a fourni finit n'abandonne pas le programme?

Q3 La fonction terminate est-elle définie par std::set_terminate dans le contexte de l'unité d'exécution qui a provoqué cet appel de fin?

Répondre

7

Q1

Oui, std::terminate peut être appelé en même temps.

Q2

La norme dit qu'il est un comportement non défini pour un terminate_handler à ne pas « terminer l'exécution du programme sans retourner à l'appelant ». Dans les implémentations que je connais, si le terminate_handler tente de revenir, normalement ou exceptionnellement, abort() sera appelée.

Q3

La fonction définie par std::terminate est une approche globale, pas un fil local. Ainsi, un fil peut avoir un impact sur l'autre.

En C++ 98/03, le terminate_handler utilisé lorsque terminate est appelé en raison d'une exception non interceptée est celui qui était en vigueur lorsque l'exception a été levée, pas celui en vigueur au moment terminate est en fait appelé (bien qu'ils sont généralement les mêmes).

En C++ 11 cela a été changé et la norme dit maintenant que le gestionnaire utilisé est celui en place au moment où terminate est appelée. Ce changement a été fait par erreur et sera probablement corrigé dans un futur brouillon. Voici la question LWG suivi de cette question:

http://cplusplus.github.com/LWG/lwg-active.html#2111

Mise à jour

Lors de la réunion du printemps 2015 à Lenexa, KS, le GTP a décidé de normaliser le comportement existant et fait non précisée lorsqu'une nouvelle terminate_handler entre en vigueur si set_terminate est appelée pendant le déroulement de la pile. C'est à dire. Les implémentations sont autorisées à suivre les règles C++ 98/03 ou les règles C++ 11. Pour rendre votre code portable, si vous devez définir un terminate_handler, faites-le lors du démarrage du programme, avant toute exception, et ne prenez pas l'habitude d'appeler set_terminate par la suite.

+0

+1.Juste pour répondre à la question dans le sujet: la fonction de terminaison fournie par l'utilisateur doit être thread safe? Qu'en est-il des autres fonctions "on disaster"? Qu'en est-il de new_handler? Ce conseil de gcc est-il dangereux d'être en double suppression: http://gcc.gnu.org/onlinedocs/libstdc++/manual/dynamic_memory.html? – PiotrNycz

+0

Puisque 'std :: terminate' peut être appelé simultanément,' terminate_handler' devrait être thread-safe. Et la même chose est vraie pour tous les autres gestionnaires spécifiés dans la norme, y compris 'new_handler'. Oui, l'exemple gcc risque d'effectuer une double suppression. Cela pourrait être résolu avec un échange atomique sur 'safety'. –

+0

"fonction définie par std :: set_terminate est un global" - Pourquoi? Certaines implémentations indiquent qu'il est local ([ms: les fonctions terminate sont gérées séparément pour chaque thread] (http://msdn.microsoft.com/fr-fr/library/aa272914 (v = vs.60) .aspx); [ibm : Vous pouvez remplacer cela par une terminaison au niveau du thread] (http://publib.boulder.ibm.com/infocenter/zos/v1r11/index.jsp?topic=/com.ibm.zos.r11.bpxbd00/setterm. htm); [sun: thread peut définir son propre] (http://www.amath.unc.edu/sysadmin/DOC4.0/c-plusplus/c%2B%2B_ug/Exception_Handling.doc.html)) Can ' t trouver la définition exacte dans le standard.http: //stackoverflow.com/q/15367060/196561 – osgx