2012-10-27 23 views
11

Jak podano w http://en.cppreference.com/w/cpp/error/terminate, istnieje wiele powodów, dla których należy odwołać wypowiedzenie. Mogę sobie wyobrazić przypadek, w którym niemal w tym samym czasie niektóre z tych przyczyn występują w dwóch wątkach.Czy funkcja dostarczana przez użytkownika terminate() ma być wątkowo bezpieczna?

Q1 Czy funkcja zakończyć ustawiony przez std::set_terminate nazwać dwa razy lub więcej w tym samym czasie, w tym samym czasie, to znaczy drugi nabór rozpoczyna się przed pierwszym zakończyła.

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

Q2 Q1 == Jeśli TAK, to co się stanie, jeśli pierwszej kolejności zakończyć się skończyła. Zgaduję, że jeśli zakończyłoby się std :: abort, to program się kończy, ale co się stanie, jeśli użytkownik zakończy działanie, nie przerwie programu?

Q3 Czy funkcja zakończenia została ustawiona przez std::set_terminate wywołana w kontekście wątku, który spowodował to zakończenie połączenia?

Odpowiedz

7

Q1

Tak std::terminate można nazwać jednocześnie.

Q2

Norma mówi, że jest niezdefiniowane zachowanie dla terminate_handler nie „zakończyć wykonywanie programu bez powrotu do rozmówcy”. W implementacjach, które znam, jeśli terminate_handler próbuje powrócić, albo normalnie, albo wyjątkowo, zostanie wywołany abort().

Q3

Funkcja ustawiona przez std::terminate jest globalny, a nie lokalny wątek. Tak więc jeden wątek może wpływać na inny.

w C++ 98/03 terminate_handler używany podczas terminate nazywa powodu nieprzechwyconego wyjątkiem jest ten, który był w istocie, gdy wyjątek, a nie ten, w efekcie po terminate faktycznie nazwie (choć zazwyczaj są takie same).

W C++ 11 zostało to zmienione, a standard mówi teraz, że używany handler jest tym, który był na miejscu w czasie, w którym jest wywoływany terminate. Zmiana została dokonana przez pomyłkę i najprawdopodobniej zostanie poprawiona w przyszłym projekcie. Tutaj jest kwestia LWG śledzenia ten problem:

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

Aktualizacja

Na spotkaniu w Lenexa, KS Wiosną 2015 r LWG postanowił ujednolicić istniejące zachowanie i uczynił to nieokreślone, gdy nowy terminate_handler wchodzi w życie, gdy set_terminate jest wywoływane podczas rozwijania stosu. To znaczy. implementacje mogą być zgodne z regułami C++ 98/03 lub C++ 11.

Aby twój kod był przenośny, jeśli chcesz ustawić terminate_handler, zrób to podczas uruchamiania programu, zanim wyjdą wyjątki i nie nawołuj po tym, aby dzwonić pod numer set_terminate.

+0

+1.Wystarczy odpowiedzieć na pytanie w temacie: funkcja zakończona przez użytkownika musi być bezpieczna dla wątków? A co z innymi funkcjami "na wypadek katastrofy"? A co z new_handler? Czy ta rada gcc jest niebezpieczna z powodu podwójnego usuwania: http://gcc.gnu.org/onlinedocs/libstdc++/manual/dynamic_memory.html? – PiotrNycz

+0

Ponieważ 'std :: terminate' może być wywołany jednocześnie,' terminate_handler' powinno być bezpieczne dla wątków. To samo dotyczy wszystkich innych procedur obsługi określonych w standardzie, w tym 'new_handler'. Tak, przykład gcc może spowodować podwójne usunięcie. Można to rozwiązać za pomocą wymiany atomowej na "bezpieczeństwo". –

+0

"funkcja ustawiona przez std :: set_terminate jest globalna" - Dlaczego? Niektóre implementacje mówią, że jest lokalna (funkcje [ms: zakończ działają osobno dla każdego wątku] (http://msdn.microsoft.com/en-us/library/aa272914 (v = vs.60) .aspx); [ibm : Możesz to zmienić, kończąc poziom wątku] (http://publib.boulder.ibm.com/infocenter/zos/v1r11/index.jsp?topic=/com.ibm.zos.r11.bpxbd00/setterm. htm); [sun: wątek może ustawiać własne] (http://www.amath.unc.edu/sysadmin/DOC4.0/c-plusplus/c%2B%2B_ug/Exception_Handling.doc.html)) Can ' t znaleźć dokładną definicję w standard.http: //stackoverflow.com/q/15367060/196561 – osgx

Powiązane problemy