2014-11-03 26 views
5

Jak bezpiecznie usuwać statyczne obiekty C++ w przypadku, gdy wiele wątków (Posix) wywołuje jednocześnie exit()?bezpieczne niszczyciele statyczne, gdy wiele wątków wywołuje exit()

Wydaje się w moim otoczeniu CentOS6 że exit() wykonuje atexit (lub on_exit) czyszczenia ładowarki wywołując coś podobnego fct[--cnt]() gdzie cnt jest liczba zarejestrowanych koparki. Gdy wiele wątków wywołuje w tym samym czasie exit(), mamy warunki wyścigu w niezabezpieczonej operacji --cnt, a niektóre programy obsługi mogą być pomijane lub wywoływane wiele razy (co prowadzi do sporadycznych awarii). Jak mogę się upewnić, że tylko jeden z wątków wywołujących exit() powoduje czyszczenie i wszystkie inne kończą się? Należy pamiętać, że wstawienie pthread_mutex_lock() do obsługi czyszczenia nie pomoże, bo to handler może zostać pominięty ...

Niestety nie można uniknąć, że wiele wątków zadzwonić exit() bo to kod moi użytkownicy będą pisać (mam zapewniając biblioteka dla nich).

Szukasz bezpiecznych pomysłów, dzięki!

+1

O co właściwie się martwisz? Czy masz coś w swoich statycznie przydzielonych obiektach, które MUSZĄ zostać sklasyfikowane (jeśli tak, to co)? Zasadniczo bezpieczne jest wyjście bez czyszczenia w nowoczesnych, wyrafinowanych systemach operacyjnych. Jeśli MUSISZ wykonać czyszczenie, sugerowałbym, że prawdopodobnie będziesz potrzebował znaleźć lepsze rozwiązanie niż pozwolić na wywołanie swojego kodu klienta - np. Zaimplementuj kod we współdzielonej bibliotece i użyj funkcji czyszczenia współdzielonej biblioteki, aby wyczyścić, być może ? Albo udokumentuj, że "nie możesz wywoływać' exit() ', używaj' my_safe_exit() '", a następnie odwołuj się do tego, gdy klienci skarżą się, że to nie działa. –

+0

Co się stanie, jeśli twoi klienci się zawierują (błąd stosu, błąd seg) lub debugowanie i wychodzenie z debuggera bez wywoływania w ogóle wyjścia? –

+0

Mam kilka obiektów statycznych, które C++ zniszczą, ale nie będą mogły bezpiecznie działać równolegle (stan wyścigu w destruktorach).To oczyszczanie jest potrzebne, na przykład, aby właściwie zamknąć strumienie plików śledzenia, więc automatyczne czyszczenie przez system operacyjny nie jest opcją. – Rainer

Odpowiedz

0

Jeśli używasz gcc, możesz skorzystać z poniższego kodu, aby określić procedurę oczyszczania:

void __attribute__ ((destructor)) my_fini(void); 

Jeśli to nie rozwiąże problemu, jak o definiowaniu pojedynczy obiekt z czasem trwania statycznego, którego destructor czy zadbasz o swoje porządki?

1

Nie ma przenośnego sposobu obsługi wielu wywołań do wyjścia() - ponieważ nie jest zdefiniowane (zachowanie), co dzieje się w takim przypadku.

Jednak w przypadku niektórych platform można znaleźć sposób na zrobienie tego. Nieco ogólnym rozwiązaniem "wywoływanego wiele razy" jest posiadanie flagi w statycznych obiektach, takich jak "jestem już zniszczony". Jak zwykle, można ukryć, że w szablonie:

template <typename T> class StaticExitHandled { 
public: 
    std::unique_ptr<T> t_; 
    ~StaticExitHandled() { t_.release(); } 
}; 

Teraz tylko pamiętać, aby zadeklarować wszystkie statycznych obiektów z tego szablonu. To jest właśnie jego rdzeń, dodaj dzwonki i gwizdki według własnego gustu. Ponadto, zamiast std :: unique_ptr <> możesz użyć boost :: optional <> lub czegoś takiego.

Nie sądzę, że istnieje ogólne rozwiązanie dla "w ogóle nie wywołanego".

Właściwie odradzam posiadanie nietrywialnych obiektów statycznych w środowisku wielowątkowym. Tak więc, tylko statyczne POD i obiekty z silnie ograniczonymi destruktorami (w zależności od tego, co jest bezpieczne w tym momencie w twoim środowisku - tj. Zamykanie uchwytów plików jest w porządku w większości środowisk).